@metaplex-foundation/kinobi 0.5.0 → 0.7.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. package/dist/cjs/nodes/InstructionNode.js +53 -15
  2. package/dist/cjs/nodes/InstructionNode.js.map +1 -1
  3. package/dist/cjs/renderers/js/GetJavaScriptRenderMapVisitor.js +84 -28
  4. package/dist/cjs/renderers/js/GetJavaScriptRenderMapVisitor.js.map +1 -1
  5. package/dist/cjs/renderers/js/GetJavaScriptTypeManifestVisitor.js +3 -0
  6. package/dist/cjs/renderers/js/GetJavaScriptTypeManifestVisitor.js.map +1 -1
  7. package/dist/cjs/renderers/js/GetJavaScriptValidatorBagVisitor.js +2 -0
  8. package/dist/cjs/renderers/js/GetJavaScriptValidatorBagVisitor.js.map +1 -1
  9. package/dist/cjs/renderers/js/templates/instructionsPage.njk +11 -24
  10. package/dist/cjs/renderers/js/templates/instructionsPageAccountMetas.njk +8 -51
  11. package/dist/cjs/renderers/js/templates/instructionsPageArgs.njk +34 -5
  12. package/dist/cjs/renderers/js/templates/instructionsPageResolvedInputs.njk +63 -0
  13. package/dist/cjs/renderers/js/templates/programsPage.njk +12 -2
  14. package/dist/cjs/visitors/BaseNodeOrNullVisitor.js +6 -1
  15. package/dist/cjs/visitors/BaseNodeOrNullVisitor.js.map +1 -1
  16. package/dist/cjs/visitors/BaseNodeVisitor.js +6 -1
  17. package/dist/cjs/visitors/BaseNodeVisitor.js.map +1 -1
  18. package/dist/cjs/visitors/BaseVoidVisitor.js +2 -0
  19. package/dist/cjs/visitors/BaseVoidVisitor.js.map +1 -1
  20. package/dist/cjs/visitors/aggregators/GetDefaultValidatorBagVisitor.js +32 -2
  21. package/dist/cjs/visitors/aggregators/GetDefaultValidatorBagVisitor.js.map +1 -1
  22. package/dist/cjs/visitors/aggregators/GetNodeInlineStringVisitor.js +4 -2
  23. package/dist/cjs/visitors/aggregators/GetNodeInlineStringVisitor.js.map +1 -1
  24. package/dist/cjs/visitors/aggregators/GetNodeTreeStringVisitor.js +6 -0
  25. package/dist/cjs/visitors/aggregators/GetNodeTreeStringVisitor.js.map +1 -1
  26. package/dist/cjs/visitors/aggregators/GetResolvedInstructionInputsVisitor.js +201 -0
  27. package/dist/cjs/visitors/aggregators/GetResolvedInstructionInputsVisitor.js.map +1 -0
  28. package/dist/cjs/visitors/aggregators/index.js +1 -1
  29. package/dist/cjs/visitors/aggregators/index.js.map +1 -1
  30. package/dist/cjs/visitors/transformers/AutoSetAnchorDiscriminatorsVisitor.js +1 -1
  31. package/dist/cjs/visitors/transformers/AutoSetAnchorDiscriminatorsVisitor.js.map +1 -1
  32. package/dist/cjs/visitors/transformers/CreateSubInstructionsFromEnumArgsVisitor.js +2 -2
  33. package/dist/cjs/visitors/transformers/CreateSubInstructionsFromEnumArgsVisitor.js.map +1 -1
  34. package/dist/cjs/visitors/transformers/FlattenInstructionArgsStructVisitor.js +1 -1
  35. package/dist/cjs/visitors/transformers/FlattenInstructionArgsStructVisitor.js.map +1 -1
  36. package/dist/cjs/visitors/transformers/SetInstructionAccountDefaultValuesVisitor.js +1 -1
  37. package/dist/cjs/visitors/transformers/SetInstructionAccountDefaultValuesVisitor.js.map +1 -1
  38. package/dist/cjs/visitors/transformers/SetInstructionDiscriminatorsVisitor.js +1 -1
  39. package/dist/cjs/visitors/transformers/SetInstructionDiscriminatorsVisitor.js.map +1 -1
  40. package/dist/cjs/visitors/transformers/UpdateInstructionsVisitor.js +8 -5
  41. package/dist/cjs/visitors/transformers/UpdateInstructionsVisitor.js.map +1 -1
  42. package/dist/cjs/visitors/transformers/UseCustomInstructionSerializerVisitor.js +1 -1
  43. package/dist/cjs/visitors/transformers/UseCustomInstructionSerializerVisitor.js.map +1 -1
  44. package/dist/types/idl/IdlInstruction.d.ts +0 -1
  45. package/dist/types/nodes/InstructionNode.d.ts +53 -14
  46. package/dist/types/renderers/js/GetJavaScriptRenderMapVisitor.d.ts +10 -2
  47. package/dist/types/renderers/js/GetJavaScriptTypeManifestVisitor.d.ts +1 -0
  48. package/dist/types/visitors/aggregators/GetResolvedInstructionInputsVisitor.d.ts +41 -0
  49. package/dist/types/visitors/aggregators/index.d.ts +1 -1
  50. package/dist/types/visitors/transformers/UpdateInstructionsVisitor.d.ts +7 -2
  51. package/package.json +1 -1
  52. package/src/idl/IdlInstruction.ts +0 -1
  53. package/src/nodes/InstructionNode.ts +99 -21
  54. package/src/renderers/js/GetJavaScriptRenderMapVisitor.ts +106 -37
  55. package/src/renderers/js/GetJavaScriptTypeManifestVisitor.ts +6 -0
  56. package/src/renderers/js/GetJavaScriptValidatorBagVisitor.ts +2 -0
  57. package/src/renderers/js/templates/instructionsPage.njk +11 -24
  58. package/src/renderers/js/templates/instructionsPageAccountMetas.njk +8 -51
  59. package/src/renderers/js/templates/instructionsPageArgs.njk +34 -5
  60. package/src/renderers/js/templates/instructionsPageResolvedInputs.njk +63 -0
  61. package/src/renderers/js/templates/programsPage.njk +12 -2
  62. package/src/visitors/BaseNodeOrNullVisitor.ts +5 -0
  63. package/src/visitors/BaseNodeVisitor.ts +5 -0
  64. package/src/visitors/BaseVoidVisitor.ts +1 -0
  65. package/src/visitors/aggregators/GetDefaultValidatorBagVisitor.ts +48 -2
  66. package/src/visitors/aggregators/GetNodeInlineStringVisitor.ts +3 -2
  67. package/src/visitors/aggregators/GetNodeTreeStringVisitor.ts +6 -0
  68. package/src/visitors/aggregators/GetResolvedInstructionInputsVisitor.ts +275 -0
  69. package/src/visitors/aggregators/index.ts +1 -1
  70. package/src/visitors/transformers/AutoSetAnchorDiscriminatorsVisitor.ts +1 -0
  71. package/src/visitors/transformers/CreateSubInstructionsFromEnumArgsVisitor.ts +2 -0
  72. package/src/visitors/transformers/FlattenInstructionArgsStructVisitor.ts +1 -0
  73. package/src/visitors/transformers/SetInstructionAccountDefaultValuesVisitor.ts +1 -0
  74. package/src/visitors/transformers/SetInstructionDiscriminatorsVisitor.ts +1 -0
  75. package/src/visitors/transformers/UpdateInstructionsVisitor.ts +19 -14
  76. package/src/visitors/transformers/UseCustomInstructionSerializerVisitor.ts +1 -0
  77. package/dist/cjs/visitors/aggregators/GetResolvedInstructionAccountsVisitor.js +0 -123
  78. package/dist/cjs/visitors/aggregators/GetResolvedInstructionAccountsVisitor.js.map +0 -1
  79. package/dist/types/visitors/aggregators/GetResolvedInstructionAccountsVisitor.d.ts +0 -18
  80. package/src/visitors/aggregators/GetResolvedInstructionAccountsVisitor.ts +0 -155
@@ -17,25 +17,15 @@ export function {{ instruction.name | camelCase }}(
17
17
  {{- '| \'payer\'' if needsPayer else '' }}
18
18
  >,
19
19
  {% set accountsType = instruction.name | pascalCase + 'InstructionAccounts' %}
20
- {% if instruction.hasPdaAccounts %}
21
- {% set argsType %}
22
- Omit<{{ instruction.name | pascalCase + 'InstructionDataArgs' }},
23
- {%- for account in instruction.pdaAccounts -%}
24
- "{{ account.pdaBumpArg }}"{% if not loop.last %} | {% endif %}
25
- {%- endfor -%}
26
- >
27
- {% endset %}
28
- {% else %}
29
- {% set argsType = instruction.name | pascalCase + 'InstructionDataArgs' %}
30
- {% endif %}
20
+ {% set argsType = instruction.name | pascalCase + 'InstructionArgs' %}
31
21
  {% if canMergeAccountsAndArgs %}
32
22
  {% set accountsObj = 'input' %}
33
23
  {% set argsObj = 'input' %}
34
- {% if instruction.hasAccounts and instruction.hasArgs %}
24
+ {% if instruction.hasAccounts and instruction.hasAnyArgs %}
35
25
  input: {{ accountsType }} & {{ argsType }},
36
26
  {% elif instruction.hasAccounts %}
37
27
  input: {{ accountsType }},
38
- {% elif instruction.hasArgs %}
28
+ {% elif instruction.hasAnyArgs %}
39
29
  input: {{ argsType }},
40
30
  {% endif %}
41
31
  {% else %}
@@ -44,7 +34,7 @@ export function {{ instruction.name | camelCase }}(
44
34
  {% if instruction.hasAccounts %}
45
35
  accounts: {{ accountsType }},
46
36
  {% endif %}
47
- {% if instruction.hasArgs %}
37
+ {% if instruction.hasAnyArgs %}
48
38
  args: {{ argsType }},
49
39
  {% endif %}
50
40
  {% endif %}
@@ -53,20 +43,15 @@ export function {{ instruction.name | camelCase }}(
53
43
  const keys: AccountMeta[] = [];
54
44
 
55
45
  // Program ID.
56
- const programId = context.programs.getPublicKey('{{ program.name | camelCase }}', '{{ program.metadata.publicKey }}');
46
+ const programId = { ...context.programs.getPublicKey('{{ program.name | camelCase }}', '{{ program.metadata.publicKey }}'), isWritable: false };
47
+
48
+ {% include "instructionsPageResolvedInputs.njk" %}
57
49
 
58
50
  {% include "instructionsPageAccountMetas.njk" -%}
59
51
 
60
52
  // Data.
61
- {% if instruction.hasArgs and instruction.hasPdaAccounts %}
62
- const data = get{{ instruction.name | pascalCase }}InstructionDataSerializer(context).serialize({
63
- ...{{ argsObj }},
64
- {% for account in instruction.pdaAccounts %}
65
- {{ account.pdaBumpArg }}: {{ account.name | camelCase }}Account.bump,
66
- {% endfor %}
67
- });
68
- {% elif instruction.hasArgs %}
69
- const data = get{{ instruction.name | pascalCase }}InstructionDataSerializer(context).serialize({{ argsObj }});
53
+ {% if instruction.hasArgs %}
54
+ const data = get{{ instruction.name | pascalCase }}InstructionDataSerializer(context).serialize(resolvedArgs);
70
55
  {% elif instruction.hasData %}
71
56
  const data = get{{ instruction.name | pascalCase }}InstructionDataSerializer(context).serialize({});
72
57
  {% else %}
@@ -81,6 +66,8 @@ export function {{ instruction.name | camelCase }}(
81
66
  const bytesCreatedOnChain = Number({{ argsObj }}.{{ bytes.name }}){% if bytes.includeHeader %} + ACCOUNT_HEADER_SIZE{% endif %};
82
67
  {% elif bytes.kind === 'account' %}
83
68
  const bytesCreatedOnChain = get{{ bytes.name | pascalCase }}Size(){% if bytes.includeHeader %} + ACCOUNT_HEADER_SIZE{% endif %};
69
+ {% elif bytes.kind === 'resolver' %}
70
+ const bytesCreatedOnChain = {{ bytes.name | camelCase }}(context, resolvedAccounts, resolvedArgs, programId);
84
71
  {% else %}
85
72
  const bytesCreatedOnChain = 0;
86
73
  {% endif %}
@@ -1,62 +1,19 @@
1
- {% if accounts.length > 0 %}
2
- // Resolved accounts.
3
- {% for account in accounts | sort(false, false, 'dependencyPosition') %}
4
- {% if not account.defaultsTo %}
5
- const {{ account.name | camelCase }}Account = {{ accountsObj }}.{{ account.name | camelCase }};
6
- {% elif account.defaultsTo.kind === 'account' %}
7
- const {{ account.name | camelCase }}Account = {{ accountsObj }}.{{ account.name | camelCase }} ?? {{ account.defaultsTo.name | camelCase }}Account;
8
- {% elif account.defaultsTo.kind === 'pda' %}
9
- const {{ account.name | camelCase }}Account = {{ accountsObj }}.{{ account.name | camelCase }} ?? find{{ account.defaultsTo.pdaAccount | pascalCase }}Pda(context,
10
- {%- if (account.defaultsTo.seeds | length) > 0 -%}
11
- {
12
- {%- for seedKey, seedValue in account.defaultsTo.seeds -%}
13
- {%- if seedValue.kind === 'value' -%}
14
- {{ seedKey }}: {{ seedValue.render }},
15
- {%- elif seedValue.kind === 'account' -%}
16
- {{ seedKey }}: publicKey({{ seedValue.name | camelCase }}Account),
17
- {%- else -%}
18
- {{ seedKey }}: {{ argsObj }}.{{ seedValue.name | camelCase }},
19
- {%- endif -%}
20
- {%- endfor -%}
21
- }
22
- {%- endif -%}
23
- );
24
- {% elif account.defaultsTo.kind === 'publicKey' %}
25
- const {{ account.name | camelCase }}Account = {{ accountsObj }}.{{ account.name | camelCase }} ?? publicKey('{{ account.defaultsTo.publicKey }}');
26
- {% elif account.defaultsTo.kind === 'program' %}
27
- const {{ account.name | camelCase }}Account = {{ accountsObj }}.{{ account.name | camelCase }} ?? { ...context.programs.getPublicKey('{{ account.defaultsTo.program.name }}', '{{ account.defaultsTo.program.publicKey }}'), isWritable: false };
28
- {% elif account.defaultsTo.kind === 'programId' %}
29
- const {{ account.name | camelCase }}Account = {{ accountsObj }}.{{ account.name | camelCase }} ?? { ...programId, isWritable: false };
30
- {% elif account.defaultsTo.kind === 'identity' and (account.isSigner !== false) %}
31
- const {{ account.name | camelCase }}Account = {{ accountsObj }}.{{ account.name | camelCase }} ?? context.identity;
32
- {% elif account.defaultsTo.kind === 'identity' %}
33
- const {{ account.name | camelCase }}Account = {{ accountsObj }}.{{ account.name | camelCase }} ?? context.identity.publicKey;
34
- {% elif account.defaultsTo.kind === 'payer' and (account.isSigner !== false) %}
35
- const {{ account.name | camelCase }}Account = {{ accountsObj }}.{{ account.name | camelCase }} ?? context.payer;
36
- {% elif account.defaultsTo.kind === 'payer' %}
37
- const {{ account.name | camelCase }}Account = {{ accountsObj }}.{{ account.name | camelCase }} ?? context.payer.publicKey;
38
- {% else %}
39
- const {{ account.name | camelCase }}Account = {{ accountsObj }}.{{ account.name | camelCase }};
40
- {% endif %}
41
- {% endfor %}
42
- {% endif %}
43
-
44
- {% for account in accounts | sort(false, false, 'position') %}
1
+ {% for account in accounts %}
45
2
  {% set isWritableString = 'true' if account.isWritable else 'false' %}
46
3
  // {{ account.name | camelCase | titleCase }}{% if account.resolvedIsOptional %} (optional){% endif %}.
47
4
  {% if account.resolvedIsOptional %}
48
- if ({{ account.name | camelCase }}Account) {
5
+ if (resolvedAccounts.{{ account.name | camelCase }}) {
49
6
  {% endif %}
50
7
  {% if account.resolvedIsSigner === 'either' %}
51
- if (isSigner({{ account.name | camelCase }}Account)) {
52
- signers.push({{ account.name | camelCase }}Account);
8
+ if (isSigner(resolvedAccounts.{{ account.name | camelCase }})) {
9
+ signers.push(resolvedAccounts.{{ account.name | camelCase }});
53
10
  }
54
- keys.push({ pubkey: publicKey({{ account.name | camelCase }}Account), isSigner: isSigner({{ account.name | camelCase }}Account), isWritable: isWritable({{ account.name | camelCase }}Account, {{ isWritableString }}) });
11
+ keys.push({ pubkey: publicKey(resolvedAccounts.{{ account.name | camelCase }}), isSigner: isSigner(resolvedAccounts.{{ account.name | camelCase }}), isWritable: isWritable(resolvedAccounts.{{ account.name | camelCase }}, {{ isWritableString }}) });
55
12
  {% elif account.resolvedIsSigner %}
56
- signers.push({{ account.name | camelCase }}Account);
57
- keys.push({ pubkey: {{ account.name | camelCase }}Account.publicKey, isSigner: true, isWritable: isWritable({{ account.name | camelCase }}Account, {{ isWritableString }}) });
13
+ signers.push(resolvedAccounts.{{ account.name | camelCase }});
14
+ keys.push({ pubkey: resolvedAccounts.{{ account.name | camelCase }}.publicKey, isSigner: true, isWritable: isWritable(resolvedAccounts.{{ account.name | camelCase }}, {{ isWritableString }}) });
58
15
  {% else %}
59
- keys.push({ pubkey: {{ account.name | camelCase }}Account, isSigner: false, isWritable: isWritable({{ account.name | camelCase }}Account, {{ isWritableString }}) });
16
+ keys.push({ pubkey: resolvedAccounts.{{ account.name | camelCase }}, isSigner: false, isWritable: isWritable(resolvedAccounts.{{ account.name | camelCase }}, {{ isWritableString }}) });
60
17
  {% endif %}
61
18
  {% if account.resolvedIsOptional %}
62
19
  }
@@ -1,7 +1,36 @@
1
- {% if not instruction.isLinked and instruction.hasData %}
2
- // Arguments.
3
- {{ macros.exportType(instruction.name | pascalCase + 'InstructionData', typeManifest) }}
1
+ {% if not instruction.hasLinkedArgs and instruction.hasData %}
2
+ // Data.
3
+ {{ macros.exportType(instruction.name | pascalCase + 'InstructionData', argManifest) }}
4
4
 
5
- {{ macros.exportSerializer(instruction.name | pascalCase + 'InstructionData', typeManifest) }}
5
+ {{ macros.exportSerializer(instruction.name | pascalCase + 'InstructionData', argManifest) }}
6
+ {% endif %}
6
7
 
7
- {% endif %}
8
+ {% if not instruction.hasLinkedExtraArgs and instruction.hasExtraArgs %}
9
+ // Extra Args.
10
+ export type {{ instruction.name | pascalCase + 'InstructionExtraArgs' }} = {{ extraArgManifest.looseType }};
11
+ {% endif %}
12
+
13
+ {% if instruction.hasAnyArgs %}
14
+ {% set argType %}
15
+ {% if instruction.hasArgs and instruction.hasExtraArgs %}
16
+ {{ instruction.name | pascalCase + 'InstructionDataArgs' }} & {{ instruction.name | pascalCase + 'InstructionExtraArgs' }}
17
+ {% elif instruction.hasArgs %}
18
+ {{ instruction.name | pascalCase + 'InstructionDataArgs' }}
19
+ {% elif instruction.hasExtraArgs %}
20
+ {{ instruction.name | pascalCase + 'InstructionExtraArgs' }}
21
+ {% endif %}
22
+ {% endset %}
23
+
24
+ // Args.
25
+ {% if argDefaultKeys.length > 0 %}
26
+ type PickPartial<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;
27
+ export type {{ instruction.name | pascalCase + 'InstructionArgs' }} = PickPartial<
28
+ {{ argType }},
29
+ {% for key in argDefaultKeys %}
30
+ "{{ key }}"{% if not loop.last %} | {% endif %}
31
+ {% endfor %}
32
+ >;
33
+ {% else %}
34
+ export type {{ instruction.name | pascalCase + 'InstructionArgs' }} = {{ argType }};
35
+ {% endif %}
36
+ {% endif %}
@@ -0,0 +1,63 @@
1
+ {% set hasResolvedAccounts = accounts.length > 0 or instruction.hasResolvers %}
2
+ {% set hasResolvedArgs = instruction.hasArgs or instruction.hasArgDefaults or instruction.hasResolvers %}
3
+
4
+ {% if resolvedInputs.length > 0 or hasResolvedAccounts or hasResolvedArgs %}
5
+ // Resolved inputs.
6
+ {% if hasResolvedAccounts %}
7
+ const resolvedAccounts: any = { ...{{ accountsObj }} };
8
+ {% endif %}
9
+ {% if hasResolvedArgs %}
10
+ const resolvedArgs: any = { ...{{ argsObj }} };
11
+ {% endif %}
12
+ {% for input in resolvedInputs %}
13
+ {% if input.kind === 'account' and input.defaultsTo %}
14
+ {% if input.defaultsTo.kind === 'account' %}
15
+ resolvedAccounts.{{ input.name | camelCase }} = resolvedAccounts.{{ input.name | camelCase }} ?? resolvedAccounts.{{ input.defaultsTo.name | camelCase }};
16
+ {% elif input.defaultsTo.kind === 'pda' %}
17
+ resolvedAccounts.{{ input.name | camelCase }} = resolvedAccounts.{{ input.name | camelCase }} ?? find{{ input.defaultsTo.pdaAccount | pascalCase }}Pda(context,
18
+ {%- if (input.defaultsTo.seeds | length) > 0 -%}
19
+ {
20
+ {%- for seedKey, seedValue in input.defaultsTo.seeds -%}
21
+ {%- if seedValue.kind === 'value' -%}
22
+ {{ seedKey }}: {{ seedValue.render }},
23
+ {%- elif seedValue.kind === 'account' -%}
24
+ {{ seedKey }}: publicKey(resolvedAccounts.{{ seedValue.name | camelCase }}),
25
+ {%- else -%}
26
+ {{ seedKey }}: resolvedArgs.{{ seedValue.name | camelCase }},
27
+ {%- endif -%}
28
+ {%- endfor -%}
29
+ }
30
+ {%- endif -%}
31
+ );
32
+ {% elif input.defaultsTo.kind === 'publicKey' %}
33
+ resolvedAccounts.{{ input.name | camelCase }} = resolvedAccounts.{{ input.name | camelCase }} ?? publicKey('{{ input.defaultsTo.publicKey }}');
34
+ {% elif input.defaultsTo.kind === 'program' %}
35
+ resolvedAccounts.{{ input.name | camelCase }} = resolvedAccounts.{{ input.name | camelCase }} ?? { ...context.programs.getPublicKey('{{ input.defaultsTo.program.name }}', '{{ input.defaultsTo.program.publicKey }}'), isWritable: false };
36
+ {% elif input.defaultsTo.kind === 'programId' %}
37
+ resolvedAccounts.{{ input.name | camelCase }} = resolvedAccounts.{{ input.name | camelCase }} ?? programId;
38
+ {% elif input.defaultsTo.kind === 'identity' and (input.isSigner !== false) %}
39
+ resolvedAccounts.{{ input.name | camelCase }} = resolvedAccounts.{{ input.name | camelCase }} ?? context.identity;
40
+ {% elif input.defaultsTo.kind === 'identity' %}
41
+ resolvedAccounts.{{ input.name | camelCase }} = resolvedAccounts.{{ input.name | camelCase }} ?? context.identity.publicKey;
42
+ {% elif input.defaultsTo.kind === 'payer' and (input.isSigner !== false) %}
43
+ resolvedAccounts.{{ input.name | camelCase }} = resolvedAccounts.{{ input.name | camelCase }} ?? context.payer;
44
+ {% elif input.defaultsTo.kind === 'payer' %}
45
+ resolvedAccounts.{{ input.name | camelCase }} = resolvedAccounts.{{ input.name | camelCase }} ?? context.payer.publicKey;
46
+ {% elif input.defaultsTo.kind === 'resolver' %}
47
+ resolvedAccounts.{{ input.name | camelCase }} = resolvedAccounts.{{ input.name | camelCase }} ?? {{ input.defaultsTo.name | camelCase }}(context, resolvedAccounts, resolvedArgs, programId);
48
+ {% endif %}
49
+ {% elif input.kind === 'arg' %}
50
+ {% if input.defaultsTo.kind === 'arg' %}
51
+ resolvedArgs.{{ input.name | camelCase }} = resolvedArgs.{{ input.name | camelCase }} ?? resolvedArgs.{{ input.defaultsTo.name | camelCase }};
52
+ {% elif input.defaultsTo.kind === 'account' %}
53
+ resolvedArgs.{{ input.name | camelCase }} = resolvedArgs.{{ input.name | camelCase }} ?? resolvedAccounts.{{ input.defaultsTo.name | camelCase }};
54
+ {% elif input.defaultsTo.kind === 'accountBump' %}
55
+ resolvedArgs.{{ input.name | camelCase }} = resolvedArgs.{{ input.name | camelCase }} ?? resolvedAccounts.{{ input.defaultsTo.name | camelCase }}.bump;
56
+ {% elif input.defaultsTo.kind === 'value' %}
57
+ resolvedArgs.{{ input.name | camelCase }} = resolvedArgs.{{ input.name | camelCase }} ?? {{ input.defaultsTo.render }};
58
+ {% elif input.defaultsTo.kind === 'resolver' %}
59
+ resolvedArgs.{{ input.name | camelCase }} = resolvedArgs.{{ input.name | camelCase }} ?? {{ input.defaultsTo.name | camelCase }}(context, resolvedAccounts, resolvedArgs, programId);
60
+ {% endif %}
61
+ {% endif %}
62
+ {% endfor %}
63
+ {% endif %}
@@ -4,11 +4,13 @@
4
4
  {% block main %}
5
5
  {{ imports }}
6
6
 
7
+ export const {{ program.name | snakeCase | upper }}_PROGRAM_ID = publicKey('{{ program.metadata.publicKey }}');
8
+
7
9
  {{ macros.docblock(program.docs) }}
8
- export function get{{ program.name | pascalCase }}Program(): Program {
10
+ export function create{{ program.name | pascalCase }}Program(): Program {
9
11
  return {
10
12
  name: '{{ program.name | camelCase }}',
11
- publicKey: publicKey('{{ program.metadata.publicKey }}'),
13
+ publicKey: {{ program.name | snakeCase | upper }}_PROGRAM_ID,
12
14
  getErrorFromCode(code: number, cause?: Error) {
13
15
  return get{{ program.name | pascalCase }}ErrorFromCode(code, this, cause);
14
16
  },
@@ -20,4 +22,12 @@ export function get{{ program.name | pascalCase }}Program(): Program {
20
22
  },
21
23
  };
22
24
  }
25
+
26
+ export function get{{ program.name | pascalCase }}Program<T extends Program = Program>(context: Pick<Context, 'programs'>, clusterFilter?: ClusterFilter): T {
27
+ return context.programs.get<T>("{{ program.name | camelCase }}", clusterFilter);
28
+ }
29
+
30
+ export function get{{ program.name | pascalCase }}ProgramId(context: Pick<Context, 'programs'>, clusterFilter?: ClusterFilter): PublicKey {
31
+ return context.programs.getPublicKey("{{ program.name | camelCase }}", {{ program.name | snakeCase | upper }}_PROGRAM_ID, clusterFilter);
32
+ }
23
33
  {% endblock %}
@@ -63,10 +63,15 @@ export class BaseNodeOrNullVisitor implements Visitor<nodes.Node | null> {
63
63
  const args = instruction.args.accept(this);
64
64
  if (args === null) return null;
65
65
  nodes.assertTypeStructOrDefinedLinkNode(args);
66
+ const extraArgs = instruction.extraArgs?.accept(this) ?? null;
67
+ if (extraArgs !== null) {
68
+ nodes.assertTypeStructOrDefinedLinkNode(args);
69
+ }
66
70
  return new nodes.InstructionNode(
67
71
  instruction.metadata,
68
72
  instruction.accounts,
69
73
  args,
74
+ extraArgs as nodes.TypeStructNode | nodes.TypeDefinedLinkNode | null,
70
75
  instruction.subInstructions
71
76
  .map((ix) => ix.accept(this))
72
77
  .filter(
@@ -51,10 +51,15 @@ export class BaseNodeVisitor implements Visitor<nodes.Node> {
51
51
  visitInstruction(instruction: nodes.InstructionNode): nodes.Node {
52
52
  const args = instruction.args.accept(this);
53
53
  nodes.assertTypeStructOrDefinedLinkNode(args);
54
+ const extraArgs = instruction.extraArgs?.accept(this) ?? null;
55
+ if (extraArgs !== null) {
56
+ nodes.assertTypeStructOrDefinedLinkNode(args);
57
+ }
54
58
  return new nodes.InstructionNode(
55
59
  instruction.metadata,
56
60
  instruction.accounts,
57
61
  args,
62
+ extraArgs as nodes.TypeStructNode | nodes.TypeDefinedLinkNode | null,
58
63
  instruction.subInstructions
59
64
  .map((ix) => ix.accept(this))
60
65
  .filter(
@@ -21,6 +21,7 @@ export abstract class BaseVoidVisitor implements Visitor<void> {
21
21
 
22
22
  visitInstruction(instruction: nodes.InstructionNode): void {
23
23
  instruction.args.accept(this);
24
+ instruction.extraArgs?.accept(this);
24
25
  instruction.subInstructions.forEach((ix) => ix.accept(this));
25
26
  }
26
27
 
@@ -1,8 +1,9 @@
1
1
  import * as nodes from '../../nodes';
2
+ import { mainCase } from '../../utils';
2
3
  import { NodeStack } from '../NodeStack';
3
4
  import { ValidatorBag } from '../ValidatorBag';
4
5
  import { Visitor } from '../Visitor';
5
- import { GetResolvedInstructionAccountsVisitor } from './GetResolvedInstructionAccountsVisitor';
6
+ import { GetResolvedInstructionInputsVisitor } from './GetResolvedInstructionInputsVisitor';
6
7
 
7
8
  export class GetDefaultValidatorBagVisitor implements Visitor<ValidatorBag> {
8
9
  protected stack: NodeStack = new NodeStack();
@@ -84,7 +85,7 @@ export class GetDefaultValidatorBagVisitor implements Visitor<ValidatorBag> {
84
85
  });
85
86
 
86
87
  // Check for cyclic dependencies in account defaults.
87
- const cyclicCheckVisitor = new GetResolvedInstructionAccountsVisitor();
88
+ const cyclicCheckVisitor = new GetResolvedInstructionInputsVisitor();
88
89
  try {
89
90
  instruction.accept(cyclicCheckVisitor);
90
91
  } catch (error) {
@@ -95,8 +96,53 @@ export class GetDefaultValidatorBagVisitor implements Visitor<ValidatorBag> {
95
96
  );
96
97
  }
97
98
 
99
+ // Check args.
98
100
  bag.mergeWith([instruction.args.accept(this)]);
99
101
 
102
+ // Check extra args.
103
+ if (instruction.extraArgs) {
104
+ bag.mergeWith([instruction.extraArgs.accept(this)]);
105
+ if (
106
+ nodes.isTypeStructNode(instruction.args) &&
107
+ nodes.isTypeStructNode(instruction.extraArgs)
108
+ ) {
109
+ const names = [
110
+ ...instruction.args.fields.map(({ name }) => mainCase(name)),
111
+ ...instruction.extraArgs.fields.map(({ name }) => mainCase(name)),
112
+ ];
113
+ const duplicates = names.filter((e, i, a) => a.indexOf(e) !== i);
114
+ const uniqueDuplicates = [...new Set(duplicates)];
115
+ const hasConflictingNames = uniqueDuplicates.length > 0;
116
+ if (hasConflictingNames) {
117
+ bag.error(
118
+ `The names of the following instruction arguments are conflicting: ` +
119
+ `[${uniqueDuplicates.join(', ')}].`,
120
+ instruction,
121
+ this.stack
122
+ );
123
+ }
124
+ }
125
+ }
126
+
127
+ // Check arg defaults.
128
+ Object.entries(instruction.metadata.argDefaults).forEach(
129
+ ([name, defaultsTo]) => {
130
+ if (defaultsTo.kind === 'accountBump') {
131
+ const defaultAccount = instruction.accounts.find(
132
+ (account) => account.name === defaultsTo.name
133
+ );
134
+ if (defaultAccount && defaultAccount.isSigner !== false) {
135
+ bag.error(
136
+ `Argument ${name} cannot default to the bump attribute of ` +
137
+ `the [${defaultsTo.name}] account as it may be a Signer.`,
138
+ instruction,
139
+ this.stack
140
+ );
141
+ }
142
+ }
143
+ }
144
+ );
145
+
100
146
  // Check sub-instructions.
101
147
  bag.mergeWith(instruction.subInstructions.map((ix) => ix.accept(this)));
102
148
 
@@ -32,11 +32,12 @@ export class GetNodeInlineStringVisitor implements Visitor<string> {
32
32
  visitInstruction(instruction: nodes.InstructionNode): string {
33
33
  const accounts = instruction.accounts.map((account) => account.name);
34
34
  const args = instruction.args.accept(this);
35
+ const extraArgs = instruction.extraArgs?.accept(this);
36
+ const extraArgsString = extraArgs ? `,extraArgs:(${extraArgs})` : '';
35
37
  return (
36
38
  `${INSTRUCTION_PREFIX}[${instruction.name}](` +
37
39
  `accounts:(${accounts.join(',')}),` +
38
- `args:(${args})` +
39
- `)`
40
+ `args:(${args})${extraArgsString})`
40
41
  );
41
42
  }
42
43
 
@@ -91,6 +91,12 @@ export class GetNodeTreeStringVisitor implements Visitor<string> {
91
91
  this.indent += 1;
92
92
  children.push(instruction.args.accept(this));
93
93
  this.indent -= 1;
94
+ if (instruction.extraArgs) {
95
+ children.push(this.indented('extra arguments:'));
96
+ this.indent += 1;
97
+ children.push(instruction.extraArgs.accept(this));
98
+ this.indent -= 1;
99
+ }
94
100
  this.indent -= 1;
95
101
  return children.join('\n');
96
102
  }