@thru/programs 0.2.25 → 0.2.28

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 (30) hide show
  1. package/dist/multicall/index.cjs +166 -24
  2. package/dist/multicall/index.cjs.map +1 -1
  3. package/dist/multicall/index.d.cts +39 -3
  4. package/dist/multicall/index.d.ts +39 -3
  5. package/dist/multicall/index.js +166 -25
  6. package/dist/multicall/index.js.map +1 -1
  7. package/dist/passkey-manager/index.cjs +1235 -345
  8. package/dist/passkey-manager/index.cjs.map +1 -1
  9. package/dist/passkey-manager/index.d.cts +45 -11
  10. package/dist/passkey-manager/index.d.ts +45 -11
  11. package/dist/passkey-manager/index.js +1225 -346
  12. package/dist/passkey-manager/index.js.map +1 -1
  13. package/package.json +2 -2
  14. package/src/multicall/abi/thru/common/primitives/types.ts +14 -9
  15. package/src/multicall/abi/thru/program/multicall/types.ts +136 -4
  16. package/src/multicall/index.ts +6 -17
  17. package/src/passkey-manager/abi/thru/blockchain/state_proof/types.ts +11 -6
  18. package/src/passkey-manager/abi/thru/common/primitives/types.ts +19 -14
  19. package/src/passkey-manager/abi/thru/program/passkey_manager/types.ts +1069 -271
  20. package/src/passkey-manager/accounts.ts +79 -40
  21. package/src/passkey-manager/constants.ts +10 -1
  22. package/src/passkey-manager/index.ts +18 -2
  23. package/src/passkey-manager/instructions/add-authority.ts +31 -3
  24. package/src/passkey-manager/instructions/create.ts +106 -11
  25. package/src/passkey-manager/instructions/invoke.ts +9 -0
  26. package/src/passkey-manager/instructions/shared.ts +15 -0
  27. package/src/passkey-manager/instructions/transfer.ts +1 -1
  28. package/src/passkey-manager/instructions/validate.ts +13 -43
  29. package/src/passkey-manager/types.ts +7 -2
  30. package/src/passkey-manager/validate.test.ts +71 -3
@@ -1,15 +1,20 @@
1
1
  import { encodeAddress } from '@thru/sdk/helpers';
2
+ import { LONG_LIVED_AUTHORITY_EXPIRY_SECONDS } from './constants';
2
3
  import {
3
4
  CredentialLookup,
4
5
  WalletAccount,
5
6
  } from './abi/thru/program/passkey_manager/types';
6
7
 
8
+ const LEGACY_WALLET_HEADER_BYTES = 9;
9
+ const LEGACY_AUTHORITY_BYTES = 65;
10
+ const AUTHORITY_DATA_BYTES = 64;
11
+
7
12
  /**
8
13
  * Parse wallet account data to extract nonce.
9
14
  */
10
15
  export function parseWalletNonce(data: Uint8Array): bigint {
11
16
  const account = WalletAccount.from_array(data);
12
- if (!account) return 0n;
17
+ if (!account) return parseLegacyWalletNonce(data) ?? 0n;
13
18
  return account.get_nonce();
14
19
  }
15
20
 
@@ -24,9 +29,7 @@ export async function fetchWalletNonce(
24
29
  const account = await sdk.accounts.get(walletAddress);
25
30
  const data = account.data?.data;
26
31
  if (!data) return 0n;
27
- const parsed = WalletAccount.from_array(data);
28
- if (!parsed) return 0n;
29
- return parsed.get_nonce();
32
+ return parseWalletNonce(data);
30
33
  }
31
34
 
32
35
  /* ------------------------------------------------------------------ */
@@ -36,17 +39,20 @@ export async function fetchWalletNonce(
36
39
  export type ParsedAuthority =
37
40
  | {
38
41
  idx: number;
42
+ expiresAtBlockTimeSeconds: bigint;
39
43
  kind: 'passkey';
40
44
  x: Uint8Array;
41
45
  y: Uint8Array;
42
46
  }
43
47
  | {
44
48
  idx: number;
49
+ expiresAtBlockTimeSeconds: bigint;
45
50
  kind: 'pubkey';
46
51
  pubkey: Uint8Array;
47
52
  }
48
53
  | {
49
54
  idx: number;
55
+ expiresAtBlockTimeSeconds: bigint;
50
56
  kind: 'unknown';
51
57
  tag: number;
52
58
  data: Uint8Array;
@@ -55,56 +61,84 @@ export type ParsedAuthority =
55
61
  export interface WalletAuthorities {
56
62
  nonce: bigint;
57
63
  authorities: ParsedAuthority[];
58
- }
59
-
60
- const AUTHORITY_HEADER_BYTES = 9; /* num_auth (u8) + nonce (u64 LE) */
61
- const AUTHORITY_ENTRY_BYTES = 65; /* tag (u8) + data (64) */
62
-
63
- function readU64LE(data: Uint8Array, offset: number): bigint {
64
- if (offset + 8 > data.length) {
65
- throw new Error('Out of bounds');
66
- }
67
- let value = 0n;
68
- for (let i = 0; i < 8; i++) {
69
- value |= BigInt(data[offset + i]) << (8n * BigInt(i));
70
- }
71
- return value;
64
+ layout: 'authorityRecord' | 'legacyAuthority';
72
65
  }
73
66
 
74
67
  /**
75
68
  * Parse the on-chain WalletAccount data buffer into its nonce and full
76
- * authority list. The on-chain layout is:
77
- *
78
- * num_auth: u8
79
- * nonce: u64 LE
80
- * authorities[num_auth + 1]: { tag: u8, data: [u8; 64] }
81
- *
82
- * (`num_auth + 1` because num_auth stores the count minus one.)
69
+ * authority list using the generated ABI view.
83
70
  */
84
71
  export function parseWalletAuthorities(data: Uint8Array): WalletAuthorities {
85
- if (data.length < AUTHORITY_HEADER_BYTES) {
86
- throw new Error('Wallet data too small');
72
+ const account = WalletAccount.from_array(data);
73
+ if (!account) {
74
+ const legacy = parseLegacyWalletAuthorities(data);
75
+ if (legacy) return legacy;
76
+ throw new Error('Wallet data truncated');
87
77
  }
88
78
 
79
+ const authorities: ParsedAuthority[] = [];
80
+ account.get_authorities().forEach((record, idx) => {
81
+ const authority = record.get_authority();
82
+ const tag = authority.get_tag();
83
+ const payload = Uint8Array.from(authority.get_data());
84
+ const expiresAtBlockTimeSeconds =
85
+ record.get_expires_at_block_time_seconds();
86
+
87
+ if (tag === 1) {
88
+ authorities.push({
89
+ idx,
90
+ expiresAtBlockTimeSeconds,
91
+ kind: 'passkey',
92
+ x: payload.slice(0, 32),
93
+ y: payload.slice(32, 64),
94
+ });
95
+ return;
96
+ }
97
+
98
+ if (tag === 2) {
99
+ authorities.push({
100
+ idx,
101
+ expiresAtBlockTimeSeconds,
102
+ kind: 'pubkey',
103
+ pubkey: payload.slice(0, 32),
104
+ });
105
+ return;
106
+ }
107
+
108
+ authorities.push({ idx, expiresAtBlockTimeSeconds, kind: 'unknown', tag, data: payload });
109
+ });
110
+
111
+ return { nonce: account.get_nonce(), authorities, layout: 'authorityRecord' };
112
+ }
113
+
114
+ function parseLegacyWalletNonce(data: Uint8Array): bigint | null {
115
+ if (data.length < LEGACY_WALLET_HEADER_BYTES) return null;
116
+ const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
117
+ return view.getBigUint64(1, true);
118
+ }
119
+
120
+ function parseLegacyWalletAuthorities(data: Uint8Array): WalletAuthorities | null {
121
+ if (data.length < LEGACY_WALLET_HEADER_BYTES) return null;
122
+
89
123
  const numAuth = data[0];
90
- const nonce = readU64LE(data, 1);
124
+ const authorityCount = numAuth + 1;
125
+ const requiredLength = LEGACY_WALLET_HEADER_BYTES + authorityCount * LEGACY_AUTHORITY_BYTES;
126
+ if (data.length < requiredLength) return null;
91
127
 
92
- const count = numAuth + 1;
93
- const required =
94
- AUTHORITY_HEADER_BYTES + count * AUTHORITY_ENTRY_BYTES;
95
- if (data.length < required) {
96
- throw new Error('Wallet data truncated');
97
- }
128
+ const nonce = parseLegacyWalletNonce(data);
129
+ if (nonce === null) return null;
98
130
 
99
131
  const authorities: ParsedAuthority[] = [];
100
- for (let idx = 0; idx < count; idx++) {
101
- const offset = AUTHORITY_HEADER_BYTES + idx * AUTHORITY_ENTRY_BYTES;
132
+ for (let idx = 0; idx < authorityCount; idx += 1) {
133
+ const offset = LEGACY_WALLET_HEADER_BYTES + idx * LEGACY_AUTHORITY_BYTES;
102
134
  const tag = data[offset];
103
- const payload = data.slice(offset + 1, offset + AUTHORITY_ENTRY_BYTES);
135
+ const payload = data.slice(offset + 1, offset + 1 + AUTHORITY_DATA_BYTES);
136
+ const expiresAtBlockTimeSeconds = LONG_LIVED_AUTHORITY_EXPIRY_SECONDS;
104
137
 
105
138
  if (tag === 1) {
106
139
  authorities.push({
107
140
  idx,
141
+ expiresAtBlockTimeSeconds,
108
142
  kind: 'passkey',
109
143
  x: payload.slice(0, 32),
110
144
  y: payload.slice(32, 64),
@@ -113,14 +147,19 @@ export function parseWalletAuthorities(data: Uint8Array): WalletAuthorities {
113
147
  }
114
148
 
115
149
  if (tag === 2) {
116
- authorities.push({ idx, kind: 'pubkey', pubkey: payload.slice(0, 32) });
150
+ authorities.push({
151
+ idx,
152
+ expiresAtBlockTimeSeconds,
153
+ kind: 'pubkey',
154
+ pubkey: payload.slice(0, 32),
155
+ });
117
156
  continue;
118
157
  }
119
158
 
120
- authorities.push({ idx, kind: 'unknown', tag, data: payload });
159
+ authorities.push({ idx, expiresAtBlockTimeSeconds, kind: 'unknown', tag, data: payload });
121
160
  }
122
161
 
123
- return { nonce, authorities };
162
+ return { nonce, authorities, layout: 'legacyAuthority' };
124
163
  }
125
164
 
126
165
  /**
@@ -1,5 +1,10 @@
1
+ import {
2
+ Authority,
3
+ AuthorityRecord,
4
+ } from './abi/thru/program/passkey_manager/types';
5
+
1
6
  export const PASSKEY_MANAGER_PROGRAM_ADDRESS =
2
- 'taUDdQyFxvM5i0HFRkEK3W45kWLyblAHSnMg4zplgUnz6Z';
7
+ 'tabsq39mzj3DZlutXOGG6VtfMj8fUvI0HIOXfZm7TLLY6N';
3
8
 
4
9
  // Instruction discriminants
5
10
  export const INSTRUCTION_CREATE = 0x00;
@@ -12,3 +17,7 @@ export const INSTRUCTION_REGISTER_CREDENTIAL = 0x06;
12
17
  // Authority tags
13
18
  export const AUTHORITY_TAG_PASSKEY = 1;
14
19
  export const AUTHORITY_TAG_PUBKEY = 2;
20
+
21
+ export const AUTHORITY_BYTES = Authority.footprint();
22
+ export const AUTHORITY_RECORD_BYTES = AuthorityRecord.footprint();
23
+ export const LONG_LIVED_AUTHORITY_EXPIRY_SECONDS = 0xffffffffffffffffn;
@@ -9,11 +9,15 @@ export {
9
9
  INSTRUCTION_REGISTER_CREDENTIAL,
10
10
  AUTHORITY_TAG_PASSKEY,
11
11
  AUTHORITY_TAG_PUBKEY,
12
+ AUTHORITY_BYTES,
13
+ AUTHORITY_RECORD_BYTES,
14
+ LONG_LIVED_AUTHORITY_EXPIRY_SECONDS,
12
15
  } from './constants';
13
16
 
14
17
  // Types
15
18
  export type {
16
19
  Authority,
20
+ AuthorityRecord,
17
21
  CreateInstructionParams,
18
22
  TransferInstructionParams,
19
23
  TargetInstructionParams,
@@ -31,12 +35,24 @@ export type {
31
35
  } from './types';
32
36
 
33
37
  // Instructions
34
- export { encodeCreateInstruction } from './instructions/create';
38
+ export {
39
+ buildAuthority,
40
+ buildAuthorityRecord,
41
+ createAuthorityRecord,
42
+ createSessionAuthorityRecord,
43
+ encodeCreateInstruction,
44
+ encodeLegacyCreateInstruction,
45
+ } from './instructions/create';
35
46
  export { encodeValidateInstruction } from './instructions/validate';
36
47
  export { encodeTransferInstruction } from './instructions/transfer';
37
- export { encodeAddAuthorityInstruction } from './instructions/add-authority';
48
+ export { encodeInvokeInstruction } from './instructions/invoke';
49
+ export {
50
+ encodeAddAuthorityInstruction,
51
+ encodeLegacyAddAuthorityInstruction,
52
+ } from './instructions/add-authority';
38
53
  export { encodeRemoveAuthorityInstruction } from './instructions/remove-authority';
39
54
  export { encodeRegisterCredentialInstruction } from './instructions/register-credential';
55
+ export { concatenateInstructions } from './instructions/shared';
40
56
 
41
57
  // Challenge
42
58
  export { createValidateChallenge, VALIDATE_CHALLENGE_DOMAIN } from './challenge';
@@ -1,9 +1,10 @@
1
1
  import type { AddAuthorityInstructionParams } from '../types';
2
+ import { INSTRUCTION_ADD_AUTHORITY } from '../constants';
2
3
  import {
3
4
  AddAuthorityArgsBuilder,
4
5
  PasskeyInstructionBuilder,
5
6
  } from '../abi/thru/program/passkey_manager/types';
6
- import { buildAuthority } from './create';
7
+ import { buildAuthority, buildAuthorityRecord } from './create';
7
8
 
8
9
  export function encodeAddAuthorityInstruction(params: AddAuthorityInstructionParams): Uint8Array {
9
10
  const { walletAccountIdx } = params;
@@ -11,11 +12,11 @@ export function encodeAddAuthorityInstruction(params: AddAuthorityInstructionPar
11
12
  throw new Error('walletAccountIdx must be 0-65535');
12
13
  }
13
14
 
14
- const authorityBytes = buildAuthority(params.authority);
15
+ const authorityRecordBytes = buildAuthorityRecord(params.authorityRecord);
15
16
 
16
17
  const argsPayload = new AddAuthorityArgsBuilder()
17
18
  .set_wallet_account_idx(walletAccountIdx)
18
- .set_authority(authorityBytes)
19
+ .set_authority_record(authorityRecordBytes)
19
20
  .build();
20
21
 
21
22
  return new PasskeyInstructionBuilder()
@@ -25,3 +26,30 @@ export function encodeAddAuthorityInstruction(params: AddAuthorityInstructionPar
25
26
  .finish()
26
27
  .build();
27
28
  }
29
+
30
+ function writeU16LE(target: Uint8Array, offset: number, value: number): void {
31
+ target[offset] = value & 0xff;
32
+ target[offset + 1] = (value >> 8) & 0xff;
33
+ }
34
+
35
+ /**
36
+ * Encode ADD_AUTHORITY for the currently deployed legacy passkey-manager.
37
+ *
38
+ * Legacy ADD_AUTHORITY appends a bare 65-byte Authority. Expiry remains a
39
+ * local wallet/session policy until the AuthorityRecord program is deployed.
40
+ */
41
+ export function encodeLegacyAddAuthorityInstruction(
42
+ params: AddAuthorityInstructionParams
43
+ ): Uint8Array {
44
+ const { walletAccountIdx } = params;
45
+ if (walletAccountIdx < 0 || walletAccountIdx > 0xffff) {
46
+ throw new Error('walletAccountIdx must be 0-65535');
47
+ }
48
+
49
+ const authorityBytes = buildAuthority(params.authorityRecord.authority);
50
+ const output = new Uint8Array(1 + 2 + authorityBytes.length);
51
+ output[0] = INSTRUCTION_ADD_AUTHORITY;
52
+ writeU16LE(output, 1, walletAccountIdx);
53
+ output.set(authorityBytes, 3);
54
+ return output;
55
+ }
@@ -1,21 +1,33 @@
1
- import type { Authority, CreateInstructionParams } from '../types';
2
1
  import {
2
+ AUTHORITY_BYTES,
3
+ AUTHORITY_RECORD_BYTES,
4
+ LONG_LIVED_AUTHORITY_EXPIRY_SECONDS,
5
+ INSTRUCTION_CREATE,
6
+ } from '../constants';
7
+ import type { Authority, AuthorityRecord, CreateInstructionParams } from '../types';
8
+ import {
9
+ Authority as AuthorityView,
3
10
  AuthorityBuilder,
11
+ AuthorityRecord as AuthorityRecordView,
4
12
  CreateArgsBuilder,
5
13
  PasskeyInstructionBuilder,
6
14
  } from '../abi/thru/program/passkey_manager/types';
7
15
 
16
+ const AUTHORITY_DATA_BYTES = AUTHORITY_BYTES - 1;
17
+ const PUBKEY_BYTES = AUTHORITY_DATA_BYTES / 2;
18
+ const U64_MAX = 0xffffffffffffffffn;
19
+
8
20
  function buildAuthority(authority: Authority): Uint8Array {
9
- const data = new Array<number>(64).fill(0);
21
+ const data = new Array<number>(AUTHORITY_DATA_BYTES).fill(0);
10
22
 
11
23
  if (authority.tag === 1) {
12
- if (authority.pubkeyX.length !== 32) throw new Error('pubkeyX must be 32 bytes');
13
- if (authority.pubkeyY.length !== 32) throw new Error('pubkeyY must be 32 bytes');
14
- for (let i = 0; i < 32; i++) data[i] = authority.pubkeyX[i];
15
- for (let i = 0; i < 32; i++) data[32 + i] = authority.pubkeyY[i];
24
+ if (authority.pubkeyX.length !== PUBKEY_BYTES) throw new Error('pubkeyX must be 32 bytes');
25
+ if (authority.pubkeyY.length !== PUBKEY_BYTES) throw new Error('pubkeyY must be 32 bytes');
26
+ for (let i = 0; i < PUBKEY_BYTES; i++) data[i] = authority.pubkeyX[i];
27
+ for (let i = 0; i < PUBKEY_BYTES; i++) data[PUBKEY_BYTES + i] = authority.pubkeyY[i];
16
28
  } else if (authority.tag === 2) {
17
- if (authority.pubkey.length !== 32) throw new Error('pubkey must be 32 bytes');
18
- for (let i = 0; i < 32; i++) data[i] = authority.pubkey[i];
29
+ if (authority.pubkey.length !== PUBKEY_BYTES) throw new Error('pubkey must be 32 bytes');
30
+ for (let i = 0; i < PUBKEY_BYTES; i++) data[i] = authority.pubkey[i];
19
31
  } else {
20
32
  throw new Error('Invalid authority tag');
21
33
  }
@@ -28,19 +40,70 @@ function buildAuthority(authority: Authority): Uint8Array {
28
40
 
29
41
  export { buildAuthority };
30
42
 
43
+ function copyGeneratedBuffer(view: unknown, label: string): Uint8Array {
44
+ const buffer = (view as { buffer?: Uint8Array }).buffer;
45
+ if (!buffer) {
46
+ throw new Error(`${label} did not expose a generated buffer`);
47
+ }
48
+ return buffer.slice();
49
+ }
50
+
51
+ function assertU64(value: bigint, label: string): void {
52
+ if (value < 0n || value > U64_MAX) {
53
+ throw new Error(`${label} must fit in u64`);
54
+ }
55
+ }
56
+
57
+ export function createAuthorityRecord(
58
+ authority: Authority,
59
+ expiresAtBlockTimeSeconds = LONG_LIVED_AUTHORITY_EXPIRY_SECONDS
60
+ ): AuthorityRecord {
61
+ return { authority, expiresAtBlockTimeSeconds };
62
+ }
63
+
64
+ export function createSessionAuthorityRecord(
65
+ params: {
66
+ pubkey: Uint8Array;
67
+ expiresAtBlockTimeSeconds: bigint;
68
+ }
69
+ ): AuthorityRecord {
70
+ return createAuthorityRecord(
71
+ { tag: 2, pubkey: params.pubkey },
72
+ params.expiresAtBlockTimeSeconds
73
+ );
74
+ }
75
+
76
+ export function buildAuthorityRecord(record: AuthorityRecord): Uint8Array {
77
+ assertU64(record.expiresAtBlockTimeSeconds, 'expiresAtBlockTimeSeconds');
78
+
79
+ const authority = AuthorityView.from_array(buildAuthority(record.authority));
80
+ if (!authority) {
81
+ throw new Error('Failed to build authority');
82
+ }
83
+
84
+ const authorityRecord = AuthorityRecordView.__tnCreateView(
85
+ new Uint8Array(AUTHORITY_RECORD_BYTES)
86
+ );
87
+ authorityRecord.set_authority(authority);
88
+ authorityRecord.set_expires_at_block_time_seconds(
89
+ record.expiresAtBlockTimeSeconds
90
+ );
91
+ return copyGeneratedBuffer(authorityRecord, 'AuthorityRecord');
92
+ }
93
+
31
94
  export function encodeCreateInstruction(params: CreateInstructionParams): Uint8Array {
32
- const { walletAccountIdx, authority, seed, stateProof } = params;
95
+ const { walletAccountIdx, authorityRecord, seed, stateProof } = params;
33
96
 
34
97
  if (seed.length !== 32) throw new Error('seed must be 32 bytes');
35
98
  if (walletAccountIdx < 0 || walletAccountIdx > 0xffff) {
36
99
  throw new Error('walletAccountIdx must be 0-65535');
37
100
  }
38
101
 
39
- const authorityBytes = buildAuthority(authority);
102
+ const authorityRecordBytes = buildAuthorityRecord(authorityRecord);
40
103
 
41
104
  const argsPayload = new CreateArgsBuilder()
42
105
  .set_wallet_account_idx(walletAccountIdx)
43
- .set_authority(authorityBytes)
106
+ .set_authority_record(authorityRecordBytes)
44
107
  .set_seed(seed)
45
108
  .set_state_proof(stateProof)
46
109
  .build();
@@ -52,3 +115,35 @@ export function encodeCreateInstruction(params: CreateInstructionParams): Uint8A
52
115
  .finish()
53
116
  .build();
54
117
  }
118
+
119
+ function writeU16LE(target: Uint8Array, offset: number, value: number): void {
120
+ target[offset] = value & 0xff;
121
+ target[offset + 1] = (value >> 8) & 0xff;
122
+ }
123
+
124
+ /**
125
+ * Encode CREATE for the currently deployed legacy passkey-manager program.
126
+ *
127
+ * Legacy CREATE stores the initial bare Authority directly:
128
+ * tag || wallet_account_idx || Authority || seed || StateProof
129
+ *
130
+ * Newer program builds should use encodeCreateInstruction, which carries a
131
+ * full AuthorityRecord with an expiry timestamp.
132
+ */
133
+ export function encodeLegacyCreateInstruction(params: CreateInstructionParams): Uint8Array {
134
+ const { walletAccountIdx, authorityRecord, seed, stateProof } = params;
135
+
136
+ if (seed.length !== 32) throw new Error('seed must be 32 bytes');
137
+ if (walletAccountIdx < 0 || walletAccountIdx > 0xffff) {
138
+ throw new Error('walletAccountIdx must be 0-65535');
139
+ }
140
+
141
+ const authorityBytes = buildAuthority(authorityRecord.authority);
142
+ const output = new Uint8Array(1 + 2 + authorityBytes.length + seed.length + stateProof.length);
143
+ output[0] = INSTRUCTION_CREATE;
144
+ writeU16LE(output, 1, walletAccountIdx);
145
+ output.set(authorityBytes, 3);
146
+ output.set(seed, 3 + authorityBytes.length);
147
+ output.set(stateProof, 3 + authorityBytes.length + seed.length);
148
+ return output;
149
+ }
@@ -0,0 +1,9 @@
1
+ export function encodeInvokeInstruction(
2
+ _programPubkey: Uint8Array,
3
+ _instruction: Uint8Array,
4
+ ): Uint8Array {
5
+ throw new Error(
6
+ 'encodeInvokeInstruction is from the legacy passkey-manager ABI. ' +
7
+ 'Migrate this flow to encodeValidateInstruction({ targetInstruction }) against the upgraded passkey manager.',
8
+ );
9
+ }
@@ -0,0 +1,15 @@
1
+ export function concatenateInstructions(instructions: Uint8Array[]): Uint8Array {
2
+ const totalLength = instructions.reduce(
3
+ (sum, instruction) => sum + instruction.length,
4
+ 0,
5
+ );
6
+ const result = new Uint8Array(totalLength);
7
+
8
+ let offset = 0;
9
+ for (const instruction of instructions) {
10
+ result.set(instruction, offset);
11
+ offset += instruction.length;
12
+ }
13
+
14
+ return result;
15
+ }
@@ -18,7 +18,7 @@ export function encodeTransferInstruction(params: TransferInstructionParams): Ui
18
18
  const argsPayload = new TransferArgsBuilder()
19
19
  .set_wallet_account_idx(walletAccountIdx)
20
20
  .set_to_account_idx(toAccountIdx)
21
- .set_amount(amount as unknown as number)
21
+ .set_amount(amount)
22
22
  .build();
23
23
 
24
24
  return new PasskeyInstructionBuilder()
@@ -1,23 +1,10 @@
1
1
  import type { ValidateInstructionParams } from '../types';
2
- import { PasskeyInstructionBuilder } from '../abi/thru/program/passkey_manager/types';
2
+ import {
3
+ PasskeyInstructionBuilder,
4
+ ValidateArgsBuilder,
5
+ } from '../abi/thru/program/passkey_manager/types';
3
6
  import { buildTargetInstructionBytes } from '../target-instruction';
4
7
 
5
- const U8_SIZE = Uint8Array.BYTES_PER_ELEMENT;
6
- const U16_SIZE = Uint16Array.BYTES_PER_ELEMENT;
7
- const P256_COORDINATE_SIZE = 32;
8
- const VALIDATE_FIXED_PREFIX_SIZE =
9
- U16_SIZE +
10
- U8_SIZE +
11
- P256_COORDINATE_SIZE +
12
- P256_COORDINATE_SIZE +
13
- U16_SIZE +
14
- U16_SIZE;
15
-
16
- function writeU16LE(target: Uint8Array, offset: number, value: number): void {
17
- target[offset] = value & 0xff;
18
- target[offset + 1] = (value >> 8) & 0xff;
19
- }
20
-
21
8
  export function encodeValidateInstruction(params: ValidateInstructionParams): Uint8Array {
22
9
  const {
23
10
  walletAccountIdx,
@@ -44,36 +31,19 @@ export function encodeValidateInstruction(params: ValidateInstructionParams): Ui
44
31
 
45
32
  const targetInstructionBytes = buildTargetInstructionBytes(targetInstruction);
46
33
 
47
- const argsPayload = new Uint8Array(
48
- VALIDATE_FIXED_PREFIX_SIZE +
49
- authenticatorData.length +
50
- clientDataJSON.length +
51
- targetInstructionBytes.length
52
- );
53
- let offset = 0;
54
-
55
- writeU16LE(argsPayload, offset, walletAccountIdx);
56
- offset += 2;
57
- argsPayload[offset] = authIdx;
58
- offset += 1;
59
- argsPayload.set(signatureR, offset);
60
- offset += signatureR.length;
61
- argsPayload.set(signatureS, offset);
62
- offset += signatureS.length;
63
- writeU16LE(argsPayload, offset, authenticatorData.length);
64
- offset += 2;
65
- writeU16LE(argsPayload, offset, clientDataJSON.length);
66
- offset += 2;
67
- argsPayload.set(authenticatorData, offset);
68
- offset += authenticatorData.length;
69
- argsPayload.set(clientDataJSON, offset);
70
- offset += clientDataJSON.length;
71
- argsPayload.set(targetInstructionBytes, offset);
34
+ const argsBuilder = new ValidateArgsBuilder()
35
+ .set_wallet_account_idx(walletAccountIdx)
36
+ .set_auth_idx(authIdx)
37
+ .set_signature_r(signatureR)
38
+ .set_signature_s(signatureS)
39
+ .set_target_instruction(targetInstructionBytes);
40
+ argsBuilder.authenticator_data().write(authenticatorData).finish();
41
+ argsBuilder.client_data().write(clientDataJSON).finish();
72
42
 
73
43
  return new PasskeyInstructionBuilder()
74
44
  .payload()
75
45
  .select('validate')
76
- .writePayload(argsPayload)
46
+ .writePayload(argsBuilder)
77
47
  .finish()
78
48
  .build();
79
49
  }
@@ -64,9 +64,14 @@ export type Authority =
64
64
  pubkey: Uint8Array; // 32 bytes
65
65
  };
66
66
 
67
+ export interface AuthorityRecord {
68
+ authority: Authority;
69
+ expiresAtBlockTimeSeconds: bigint;
70
+ }
71
+
67
72
  export interface CreateInstructionParams {
68
73
  walletAccountIdx: number;
69
- authority: Authority;
74
+ authorityRecord: AuthorityRecord;
70
75
  seed: Uint8Array;
71
76
  stateProof: Uint8Array;
72
77
  }
@@ -94,7 +99,7 @@ export interface ValidateInstructionParams {
94
99
 
95
100
  export interface AddAuthorityInstructionParams {
96
101
  walletAccountIdx: number;
97
- authority: Authority;
102
+ authorityRecord: AuthorityRecord;
98
103
  }
99
104
 
100
105
  export interface RemoveAuthorityInstructionParams {