|
@@ -73,12 +73,6 @@ export class AccountsResolver<IDL extends Idl, I extends AllInstructions<IDL>> {
|
|
|
// Note: We serially resolve PDAs one by one rather than doing them
|
|
|
// in parallel because there can be dependencies between
|
|
|
// addresses. That is, one PDA can be used as a seed in another.
|
|
|
- //
|
|
|
- // TODO: PDAs need to be resolved in topological order. For now, we
|
|
|
- // require the developer to simply list the accounts in the
|
|
|
- // correct order. But in future work, we should create the
|
|
|
- // dependency graph and resolve automatically.
|
|
|
- //
|
|
|
public async resolve() {
|
|
|
await this.resolveConst(this._idlIx.accounts);
|
|
|
|
|
@@ -253,14 +247,16 @@ export class AccountsResolver<IDL extends Idl, I extends AllInstructions<IDL>> {
|
|
|
throw new Error("Must have seeds");
|
|
|
|
|
|
const seeds: (Buffer | undefined)[] = await Promise.all(
|
|
|
- accountDesc.pda.seeds.map((seedDesc: IdlSeed) => this.toBuffer(seedDesc))
|
|
|
+ accountDesc.pda.seeds.map((seedDesc: IdlSeed) =>
|
|
|
+ this.toBuffer(seedDesc, path)
|
|
|
+ )
|
|
|
);
|
|
|
|
|
|
if (seeds.some((seed) => typeof seed == "undefined")) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- const programId = await this.parseProgramId(accountDesc);
|
|
|
+ const programId = await this.parseProgramId(accountDesc, path);
|
|
|
if (!programId) {
|
|
|
return;
|
|
|
}
|
|
@@ -272,7 +268,10 @@ export class AccountsResolver<IDL extends Idl, I extends AllInstructions<IDL>> {
|
|
|
this.set([...path, camelCase(accountDesc.name)], pubkey);
|
|
|
}
|
|
|
|
|
|
- private async parseProgramId(accountDesc: IdlAccount): Promise<PublicKey> {
|
|
|
+ private async parseProgramId(
|
|
|
+ accountDesc: IdlAccount,
|
|
|
+ path: string[] = []
|
|
|
+ ): Promise<PublicKey> {
|
|
|
if (!accountDesc.pda?.programId) {
|
|
|
return this._programId;
|
|
|
}
|
|
@@ -284,7 +283,7 @@ export class AccountsResolver<IDL extends Idl, I extends AllInstructions<IDL>> {
|
|
|
case "arg":
|
|
|
return this.argValue(accountDesc.pda.programId);
|
|
|
case "account":
|
|
|
- return await this.accountValue(accountDesc.pda.programId);
|
|
|
+ return await this.accountValue(accountDesc.pda.programId, path);
|
|
|
default:
|
|
|
throw new Error(
|
|
|
`Unexpected program seed kind: ${accountDesc.pda.programId.kind}`
|
|
@@ -292,14 +291,17 @@ export class AccountsResolver<IDL extends Idl, I extends AllInstructions<IDL>> {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- private async toBuffer(seedDesc: IdlSeed): Promise<Buffer | undefined> {
|
|
|
+ private async toBuffer(
|
|
|
+ seedDesc: IdlSeed,
|
|
|
+ path: string[] = []
|
|
|
+ ): Promise<Buffer | undefined> {
|
|
|
switch (seedDesc.kind) {
|
|
|
case "const":
|
|
|
return this.toBufferConst(seedDesc);
|
|
|
case "arg":
|
|
|
return await this.toBufferArg(seedDesc);
|
|
|
case "account":
|
|
|
- return await this.toBufferAccount(seedDesc);
|
|
|
+ return await this.toBufferAccount(seedDesc, path);
|
|
|
default:
|
|
|
throw new Error(`Unexpected seed kind: ${seedDesc.kind}`);
|
|
|
}
|
|
@@ -361,20 +363,24 @@ export class AccountsResolver<IDL extends Idl, I extends AllInstructions<IDL>> {
|
|
|
}
|
|
|
|
|
|
private async toBufferAccount(
|
|
|
- seedDesc: IdlSeed
|
|
|
+ seedDesc: IdlSeed,
|
|
|
+ path: string[] = []
|
|
|
): Promise<Buffer | undefined> {
|
|
|
- const accountValue = await this.accountValue(seedDesc);
|
|
|
+ const accountValue = await this.accountValue(seedDesc, path);
|
|
|
if (!accountValue) {
|
|
|
return;
|
|
|
}
|
|
|
return this.toBufferValue(seedDesc.type, accountValue);
|
|
|
}
|
|
|
|
|
|
- private async accountValue(seedDesc: IdlSeed): Promise<any> {
|
|
|
+ private async accountValue(
|
|
|
+ seedDesc: IdlSeed,
|
|
|
+ path: string[] = []
|
|
|
+ ): Promise<any> {
|
|
|
const pathComponents = seedDesc.path.split(".");
|
|
|
|
|
|
const fieldName = pathComponents[0];
|
|
|
- const fieldPubkey = this._accounts[camelCase(fieldName)];
|
|
|
+ const fieldPubkey = this.get([...path, camelCase(fieldName)]);
|
|
|
|
|
|
// The seed is a pubkey of the account.
|
|
|
if (pathComponents.length === 1) {
|