@actioncodes/protocol 1.2.1 → 2.0.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 (144) hide show
  1. package/LICENSE +2 -2
  2. package/README.md +32 -45
  3. package/dist/ActionCodesProtocol.d.ts +35 -0
  4. package/dist/ActionCodesProtocol.d.ts.map +1 -0
  5. package/dist/adapters/BaseChainAdapter.d.ts +22 -0
  6. package/dist/adapters/BaseChainAdapter.d.ts.map +1 -0
  7. package/dist/adapters/SolanaAdapter.d.ts +44 -0
  8. package/dist/adapters/SolanaAdapter.d.ts.map +1 -0
  9. package/dist/constants.d.ts +6 -8
  10. package/dist/constants.d.ts.map +1 -1
  11. package/dist/errors.d.ts +63 -0
  12. package/dist/errors.d.ts.map +1 -0
  13. package/dist/index.cjs +3 -0
  14. package/dist/index.cjs.map +25 -0
  15. package/dist/index.d.ts +10 -8
  16. package/dist/index.d.ts.map +1 -1
  17. package/dist/index.js +3 -23
  18. package/dist/index.js.map +25 -0
  19. package/dist/strategy/DelegationStrategy.d.ts +43 -0
  20. package/dist/strategy/DelegationStrategy.d.ts.map +1 -0
  21. package/dist/strategy/WalletStrategy.d.ts +8 -0
  22. package/dist/strategy/WalletStrategy.d.ts.map +1 -0
  23. package/dist/types.d.ts +40 -0
  24. package/dist/types.d.ts.map +1 -0
  25. package/dist/utils/canonical.d.ts +5 -0
  26. package/dist/utils/canonical.d.ts.map +1 -0
  27. package/dist/utils/crypto.d.ts +13 -0
  28. package/dist/utils/crypto.d.ts.map +1 -0
  29. package/dist/utils/protocolMeta.d.ts +16 -0
  30. package/dist/utils/protocolMeta.d.ts.map +1 -0
  31. package/docs/ActionCodesProtocol/README.md +11 -0
  32. package/docs/ActionCodesProtocol/classes/ActionCodesProtocol.md +147 -0
  33. package/docs/README.md +10 -50
  34. package/docs/adapters/BaseChainAdapter/README.md +20 -0
  35. package/docs/adapters/BaseChainAdapter/classes/BaseChainAdapter.md +56 -0
  36. package/docs/adapters/BaseChainAdapter/interfaces/BaseContext.md +17 -0
  37. package/docs/adapters/BaseChainAdapter/interfaces/ChainAdapter.md +33 -0
  38. package/docs/adapters/BaseChainAdapter/type-aliases/ChainContext.md +23 -0
  39. package/docs/adapters/NodeCryptoAdapter/README.md +15 -0
  40. package/docs/adapters/NodeCryptoAdapter/classes/NodeCryptoAdapter.md +254 -0
  41. package/docs/adapters/NodeCryptoAdapter/type-aliases/NodeCryptoContext.md +27 -0
  42. package/docs/adapters/SolanaAdapter/README.md +16 -0
  43. package/docs/adapters/SolanaAdapter/classes/SolanaAdapter.md +190 -0
  44. package/docs/adapters/SolanaAdapter/type-aliases/SolanaContext.md +27 -0
  45. package/docs/adapters/SolanaAdapter/type-aliases/SolanaTransaction.md +13 -0
  46. package/docs/constants/README.md +8 -13
  47. package/docs/constants/variables/CODE_CHARSET_DIGITS.md +11 -0
  48. package/docs/constants/variables/CODE_DEFAULT_LENGTH.md +11 -0
  49. package/docs/constants/variables/CODE_MAX_LENGTH.md +11 -0
  50. package/docs/constants/variables/CODE_MIN_LENGTH.md +11 -0
  51. package/docs/constants/variables/PROTOCOL_META_MAX_BYTES.md +11 -0
  52. package/docs/constants/variables/PROTOCOL_NORMALIZATION.md +11 -0
  53. package/docs/constants/variables/SUPPORTED_CHAINS.md +3 -3
  54. package/docs/errors/README.md +22 -0
  55. package/docs/errors/classes/ExpiredCodeError.md +695 -0
  56. package/docs/errors/classes/InvalidCodeFormatError.md +691 -0
  57. package/docs/errors/classes/InvalidPubkeyFormatError.md +691 -0
  58. package/docs/errors/classes/InvalidSignatureError.md +687 -0
  59. package/docs/errors/classes/MetaMismatchError.md +695 -0
  60. package/docs/errors/classes/MissingMetaError.md +681 -0
  61. package/docs/errors/classes/ProtocolError.md +637 -0
  62. package/docs/errors/classes/TransactionNotSignedByIntendedOwnerError.md +691 -0
  63. package/docs/errors/enumerations/ProtocolErrorCode.md +121 -0
  64. package/docs/index/README.md +83 -41
  65. package/docs/modules.md +12 -9
  66. package/docs/strategy/WalletStrategy/README.md +11 -0
  67. package/docs/strategy/WalletStrategy/classes/WalletStrategy.md +67 -0
  68. package/docs/types/README.md +14 -0
  69. package/docs/types/interfaces/ActionCode.md +65 -0
  70. package/docs/types/interfaces/CanonicalMessageParts.md +33 -0
  71. package/docs/types/interfaces/CodeGenerationConfig.md +33 -0
  72. package/docs/types/interfaces/CodeGenerationResult.md +25 -0
  73. package/docs/utils/canonical/README.md +16 -0
  74. package/docs/utils/canonical/functions/serializeCanonical.md +21 -0
  75. package/docs/utils/canonical/variables/CANONICAL_MESSAGE_PREFIX.md +11 -0
  76. package/docs/utils/canonical/variables/CANONICAL_MESSAGE_VERSION.md +11 -0
  77. package/docs/utils/crypto/README.md +18 -0
  78. package/docs/utils/crypto/functions/base32EncodeCrockford.md +21 -0
  79. package/docs/utils/crypto/functions/codeHash.md +21 -0
  80. package/docs/utils/crypto/functions/digestToDigits.md +25 -0
  81. package/docs/utils/crypto/functions/generateRandomSecret.md +15 -0
  82. package/docs/utils/crypto/functions/hkdfSha256.md +35 -0
  83. package/docs/utils/crypto/functions/hmacSha256.md +25 -0
  84. package/docs/utils/crypto/functions/sha256.md +21 -0
  85. package/docs/utils/crypto/functions/truncateBits.md +25 -0
  86. package/docs/utils/protocolMeta/README.md +21 -0
  87. package/docs/utils/protocolMeta/functions/buildProtocolMeta.md +21 -0
  88. package/docs/utils/protocolMeta/functions/parseProtocolMeta.md +21 -0
  89. package/docs/utils/protocolMeta/functions/validateProtocolMetaFormat.md +21 -0
  90. package/docs/utils/protocolMeta/interfaces/ProtocolMetaFields.md +41 -0
  91. package/docs/utils/protocolMeta/variables/SCHEME.md +11 -0
  92. package/package.json +42 -47
  93. package/dist/actioncode.d.ts +0 -120
  94. package/dist/actioncode.d.ts.map +0 -1
  95. package/dist/actioncode.js +0 -173
  96. package/dist/adapters/base.d.ts +0 -93
  97. package/dist/adapters/base.d.ts.map +0 -1
  98. package/dist/adapters/base.js +0 -52
  99. package/dist/adapters/solana/index.d.ts +0 -2
  100. package/dist/adapters/solana/index.d.ts.map +0 -1
  101. package/dist/adapters/solana/index.js +0 -17
  102. package/dist/adapters/solana/solana.d.ts +0 -113
  103. package/dist/adapters/solana/solana.d.ts.map +0 -1
  104. package/dist/adapters/solana/solana.js +0 -524
  105. package/dist/codegen.d.ts +0 -76
  106. package/dist/codegen.d.ts.map +0 -1
  107. package/dist/codegen.js +0 -198
  108. package/dist/constants.js +0 -11
  109. package/dist/meta.d.ts +0 -54
  110. package/dist/meta.d.ts.map +0 -1
  111. package/dist/meta.js +0 -91
  112. package/dist/protocol.d.ts +0 -179
  113. package/dist/protocol.d.ts.map +0 -1
  114. package/dist/protocol.js +0 -377
  115. package/docs/_media/LICENSE +0 -201
  116. package/docs/_media/README.md +0 -28
  117. package/docs/actioncode/README.md +0 -21
  118. package/docs/actioncode/classes/ActionCode.md +0 -430
  119. package/docs/actioncode/interfaces/ActionCodeFields.md +0 -89
  120. package/docs/actioncode/interfaces/ActionCodeMetadata.md +0 -25
  121. package/docs/actioncode/interfaces/ActionCodeTransaction.md +0 -57
  122. package/docs/actioncode/type-aliases/ActionCodeStatus.md +0 -11
  123. package/docs/adapters/base/README.md +0 -11
  124. package/docs/adapters/base/classes/BaseChainAdapter.md +0 -396
  125. package/docs/adapters/solana/README.md +0 -19
  126. package/docs/adapters/solana/solana/README.md +0 -15
  127. package/docs/adapters/solana/solana/classes/SolanaAdapter.md +0 -506
  128. package/docs/adapters/solana/solana/type-aliases/SolanaTransaction.md +0 -13
  129. package/docs/codegen/README.md +0 -11
  130. package/docs/codegen/classes/CodeGenerator.md +0 -341
  131. package/docs/constants/type-aliases/SupportedChain.md +0 -11
  132. package/docs/constants/variables/CODE_LENGTH.md +0 -11
  133. package/docs/constants/variables/CODE_TTL.md +0 -11
  134. package/docs/constants/variables/MAX_PREFIX_LENGTH.md +0 -11
  135. package/docs/constants/variables/MIN_PREFIX_LENGTH.md +0 -11
  136. package/docs/constants/variables/PROTOCOL_CODE_PREFIX.md +0 -11
  137. package/docs/constants/variables/PROTOCOL_PREFIX.md +0 -11
  138. package/docs/constants/variables/PROTOCOL_VERSION.md +0 -11
  139. package/docs/meta/README.md +0 -15
  140. package/docs/meta/classes/ProtocolMetaParser.md +0 -177
  141. package/docs/meta/interfaces/ProtocolMetaV1.md +0 -59
  142. package/docs/protocol/README.md +0 -51
  143. package/docs/protocol/classes/ActionCodesProtocol.md +0 -676
  144. package/docs/protocol/interfaces/ProtocolConfig.md +0 -71
@@ -1,524 +0,0 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
35
- var __importDefault = (this && this.__importDefault) || function (mod) {
36
- return (mod && mod.__esModule) ? mod : { "default": mod };
37
- };
38
- Object.defineProperty(exports, "__esModule", { value: true });
39
- exports.SolanaAdapter = void 0;
40
- const web3_js_1 = require("@solana/web3.js");
41
- const spl_memo_1 = require("@solana/spl-memo");
42
- const meta_1 = require("../../meta");
43
- const base_1 = require("../base");
44
- const nacl = __importStar(require("tweetnacl"));
45
- const actioncode_1 = require("../../actioncode");
46
- const buffer_1 = require("buffer");
47
- const bs58_1 = __importDefault(require("bs58"));
48
- /**
49
- * Simple Solana adapter for protocol meta operations
50
- * Supports both legacy and versioned transactions
51
- */
52
- class SolanaAdapter extends base_1.BaseChainAdapter {
53
- constructor() {
54
- super(...arguments);
55
- this.chain = 'solana';
56
- }
57
- /**
58
- * Encode protocol meta as a Solana memo instruction
59
- * @param meta - The protocol meta to encode
60
- * @returns TransactionInstruction for the memo
61
- */
62
- encodeMeta(meta) {
63
- const metaString = meta_1.ProtocolMetaParser.serialize(meta);
64
- const signerPubkeys = [];
65
- try {
66
- if (meta.iss && meta.iss !== 'undefined') {
67
- const pubkey = new web3_js_1.PublicKey(meta.iss);
68
- signerPubkeys.push(pubkey);
69
- }
70
- }
71
- catch (error) {
72
- // Ignore error, issuer is not a valid public key
73
- }
74
- return (0, spl_memo_1.createMemoInstruction)(metaString, signerPubkeys);
75
- }
76
- /**
77
- * Decode protocol meta from Solana transaction (legacy or versioned)
78
- * @param tx - The Solana transaction (can be deserialized object or base64 string)
79
- * @returns Decoded ProtocolMetaV1 or null if not found
80
- */
81
- decodeMeta(tx) {
82
- // If it's a string, deserialize it first
83
- if (typeof tx === 'string') {
84
- try {
85
- tx = this.deserializeTransaction(tx);
86
- }
87
- catch {
88
- return null;
89
- }
90
- }
91
- // Check if it's a versioned transaction
92
- if ('message' in tx && tx.message) {
93
- return this.decodeVersionedTransaction(tx);
94
- }
95
- else if ('instructions' in tx && Array.isArray(tx.instructions)) {
96
- return this.decodeLegacyTransaction(tx);
97
- }
98
- else {
99
- return null;
100
- }
101
- }
102
- /**
103
- * Deserialize a Solana transaction from base64 string
104
- * @param base64String - Base64 encoded transaction
105
- * @returns SolanaTransaction object
106
- */
107
- deserializeTransaction(base64String) {
108
- try {
109
- const buffer = buffer_1.Buffer.from(base64String, 'base64');
110
- // Try legacy first, then versioned
111
- try {
112
- return web3_js_1.Transaction.from(buffer);
113
- }
114
- catch {
115
- return web3_js_1.VersionedTransaction.deserialize(buffer);
116
- }
117
- }
118
- catch (error) {
119
- throw new Error('Failed to deserialize Solana transaction');
120
- }
121
- }
122
- /**
123
- * Inject protocol meta into Solana transaction
124
- * @param serializedTx - Serialized transaction string (base64)
125
- * @param meta - ProtocolMetaV1 object
126
- * @returns Serialized transaction with injected meta
127
- */
128
- injectMeta(serializedTx, meta) {
129
- // Deserialize the transaction using existing pattern
130
- const tx = this.deserializeTransaction(serializedTx);
131
- const metaIx = this.encodeMeta(meta);
132
- if (tx instanceof web3_js_1.VersionedTransaction) {
133
- // Convert TransactionInstruction to MessageCompiledInstruction for versioned transactions
134
- // Create new static account keys array with all required keys
135
- const newStaticAccountKeys = [...tx.message.staticAccountKeys];
136
- // Add any missing keys from the memo instruction
137
- metaIx.keys.forEach(({ pubkey }) => {
138
- if (!newStaticAccountKeys.some(key => key.equals(pubkey))) {
139
- newStaticAccountKeys.push(pubkey);
140
- }
141
- });
142
- // Ensure programId is also in static keys
143
- if (!newStaticAccountKeys.some(key => key.equals(metaIx.programId))) {
144
- newStaticAccountKeys.push(metaIx.programId);
145
- }
146
- // Create new compiled instructions array
147
- const newCompiledInstructions = [...tx.message.compiledInstructions];
148
- // Find the program ID index in the new static keys
149
- const programIdIndex = newStaticAccountKeys.findIndex(key => key.equals(metaIx.programId));
150
- const accountKeyIndexes = metaIx.keys.map(key => {
151
- const index = newStaticAccountKeys.findIndex(staticKey => staticKey.equals(key.pubkey));
152
- if (index === -1) {
153
- throw new Error(`Account key ${key.pubkey.toBase58()} not found in static account keys`);
154
- }
155
- return index;
156
- });
157
- const compiledInstruction = {
158
- programIdIndex,
159
- accountKeyIndexes,
160
- data: metaIx.data
161
- };
162
- newCompiledInstructions.push(compiledInstruction);
163
- // Create new MessageV0 with updated data
164
- const newMessage = new web3_js_1.MessageV0({
165
- header: tx.message.header,
166
- staticAccountKeys: newStaticAccountKeys,
167
- recentBlockhash: tx.message.recentBlockhash,
168
- compiledInstructions: newCompiledInstructions,
169
- addressTableLookups: tx.message.addressTableLookups,
170
- });
171
- // Create new VersionedTransaction
172
- const newVersionedTx = new web3_js_1.VersionedTransaction(newMessage);
173
- return buffer_1.Buffer.from(newVersionedTx.serialize()).toString('base64');
174
- }
175
- else if (tx instanceof web3_js_1.Transaction) {
176
- tx.instructions.push(metaIx);
177
- // Clear existing signatures since we modified the transaction
178
- tx.signatures = [];
179
- // Serialize the transaction back without requiring signatures
180
- return tx.serialize({ requireAllSignatures: false }).toString('base64');
181
- }
182
- else {
183
- throw new Error('Invalid transaction type');
184
- }
185
- }
186
- /**
187
- * Validate transaction with protocol meta and authority list
188
- * @param tx - The Solana transaction
189
- * @param authorities - Array of valid protocol authority public keys (base58)
190
- * @param expectedPrefix - Expected protocol prefix (default: 'DEFAULT')
191
- * @returns True if transaction is valid
192
- */
193
- validate(tx, authorities, expectedPrefix = 'DEFAULT') {
194
- return this.detectTampering(tx, authorities, expectedPrefix);
195
- }
196
- /**
197
- * Check if the issuer has signed the transaction
198
- * @param tx - The Solana transaction (can be deserialized object or base64 string)
199
- * @param issuer - Issuer public key to check
200
- * @returns True if issuer has signed
201
- */
202
- hasIssuerSignature(tx, issuer) {
203
- // If it's a string, deserialize it first
204
- if (typeof tx === 'string') {
205
- try {
206
- tx = this.deserializeTransaction(tx);
207
- }
208
- catch {
209
- return false;
210
- }
211
- }
212
- // Check if it's a versioned transaction
213
- if ('message' in tx && tx.message) {
214
- return this.hasIssuerSignatureVersioned(tx, issuer);
215
- }
216
- else if ('signatures' in tx && Array.isArray(tx.signatures)) {
217
- return this.hasIssuerSignatureLegacy(tx, issuer);
218
- }
219
- else {
220
- return false;
221
- }
222
- }
223
- /**
224
- * Decode protocol meta from legacy Solana transaction
225
- */
226
- decodeLegacyTransaction(transaction) {
227
- for (const instruction of transaction.instructions) {
228
- if (instruction.programId.equals(SolanaAdapter.MEMO_PROGRAM_ID)) {
229
- const memoData = instruction.data;
230
- if (memoData && memoData.length > 0) {
231
- try {
232
- const memoString = new TextDecoder().decode(memoData);
233
- const meta = meta_1.ProtocolMetaParser.parse(memoString);
234
- if (meta && meta.version === '1') {
235
- return meta;
236
- }
237
- // Continue searching if this memo is not a valid protocol meta
238
- }
239
- catch {
240
- // Continue searching if this memo cannot be parsed
241
- }
242
- }
243
- }
244
- }
245
- return null;
246
- }
247
- /**
248
- * Decode protocol meta from versioned Solana transaction
249
- */
250
- decodeVersionedTransaction(transaction) {
251
- const message = transaction.message;
252
- if (message instanceof web3_js_1.MessageV0) {
253
- return this.decodeMessageV0(message);
254
- }
255
- else {
256
- return null;
257
- }
258
- }
259
- /**
260
- * Decode protocol meta from MessageV0
261
- */
262
- decodeMessageV0(message) {
263
- for (const instruction of message.compiledInstructions) {
264
- const programId = message.staticAccountKeys[instruction.programIdIndex];
265
- if (programId.equals(SolanaAdapter.MEMO_PROGRAM_ID)) {
266
- const memoData = instruction.data;
267
- if (memoData && memoData.length > 0) {
268
- try {
269
- const memoString = new TextDecoder().decode(memoData);
270
- const meta = meta_1.ProtocolMetaParser.parse(memoString);
271
- if (meta && meta.version === '1') {
272
- return meta;
273
- }
274
- // Continue searching if this memo is not a valid protocol meta
275
- }
276
- catch {
277
- // Continue searching if this memo cannot be parsed
278
- }
279
- }
280
- }
281
- }
282
- return null;
283
- }
284
- /**
285
- * Check if the issuer has signed a legacy transaction
286
- */
287
- hasIssuerSignatureLegacy(transaction, issuer) {
288
- return transaction.signatures.some(sig => sig.publicKey.toBase58() === issuer);
289
- }
290
- /**
291
- * Check if the issuer has signed a versioned transaction
292
- */
293
- hasIssuerSignatureVersioned(transaction, issuer) {
294
- const message = transaction.message;
295
- if (message instanceof web3_js_1.MessageV0) {
296
- // Check static account keys
297
- for (const key of message.staticAccountKeys) {
298
- if (key.toBase58() === issuer) {
299
- return true;
300
- }
301
- }
302
- }
303
- return false;
304
- }
305
- /**
306
- * Validate Solana transaction integrity with additional checks
307
- * @param tx - The Solana transaction
308
- * @param meta - Decoded protocol meta
309
- * @returns True if transaction integrity is valid
310
- */
311
- validateTransactionIntegrity(tx, meta) {
312
- // Additional Solana-specific validation can be added here
313
- // For example, checking transaction signatures, recent blockhash, etc.
314
- // Verify that the memo instruction contains the expected protocol meta
315
- const decodedMeta = this.decodeMeta(tx);
316
- if (!decodedMeta) {
317
- return false;
318
- }
319
- if (!meta.iss) {
320
- return false;
321
- }
322
- if (!this.hasIssuerSignature(tx, meta.iss)) {
323
- return false;
324
- }
325
- // Cross-check the decoded meta with the provided meta
326
- return (decodedMeta.version === meta.version &&
327
- decodedMeta.prefix === meta.prefix &&
328
- decodedMeta.initiator === meta.initiator &&
329
- decodedMeta.id === meta.id &&
330
- decodedMeta.iss === meta.iss &&
331
- decodedMeta.params === meta.params);
332
- }
333
- verifyCodeSignature(actionCode) {
334
- try {
335
- const message = this.getCodeSignatureMessage(actionCode.code, actionCode.timestamp, actionCode.prefix);
336
- const messageBytes = new TextEncoder().encode(message);
337
- const pubkeyBytes = new web3_js_1.PublicKey(actionCode.pubkey).toBytes();
338
- const sigBytes = bs58_1.default.decode(actionCode.signature);
339
- return nacl.sign.detached.verify(messageBytes, sigBytes, pubkeyBytes);
340
- }
341
- catch (error) {
342
- return false;
343
- }
344
- }
345
- /**
346
- * Decode protocol meta from base64 string (for backward compatibility)
347
- * @param base64String - Base64 encoded transaction
348
- * @returns Decoded ProtocolMetaV1 or null
349
- */
350
- decodeFromBase64(base64String) {
351
- return this.decodeMeta(base64String);
352
- }
353
- /**
354
- * Sign the transaction with the protocol key
355
- * @param actionCode - The action code containing the transaction
356
- * @param key - The keypair to sign with
357
- * @returns Promise that resolves to the signed action code
358
- */
359
- async signWithProtocolKey(actionCode, key) {
360
- try {
361
- if (!actionCode.transaction?.transaction) {
362
- throw new Error('No transaction found');
363
- }
364
- const tx = this.deserializeTransaction(actionCode.transaction.transaction);
365
- // Check if transaction has protocol meta
366
- const meta = this.decodeMeta(tx);
367
- if (!meta) {
368
- throw new Error('Invalid transaction, protocol meta not found');
369
- }
370
- // Validate transaction integrity
371
- if (!this.validateTransactionIntegrity(tx, meta)) {
372
- throw new Error('Invalid transaction, transaction integrity not valid');
373
- }
374
- // Sign the transaction
375
- if (tx instanceof web3_js_1.Transaction) {
376
- tx.partialSign(key);
377
- }
378
- else if (tx instanceof web3_js_1.VersionedTransaction) {
379
- tx.sign([key]);
380
- }
381
- else {
382
- throw new Error('Invalid transaction type');
383
- }
384
- const updatedTransaction = {
385
- ...actionCode.transaction,
386
- transaction: tx.serialize({ requireAllSignatures: false }).toString('base64'),
387
- };
388
- const updatedFields = {
389
- ...actionCode.json,
390
- transaction: updatedTransaction,
391
- };
392
- return actioncode_1.ActionCode.fromPayload(updatedFields);
393
- }
394
- catch (error) {
395
- throw new Error(`Failed to sign transaction with protocol key: ${error instanceof Error ? error.message : 'Unknown error'}`);
396
- }
397
- }
398
- /**
399
- * Verify the finalized transaction from blockchain
400
- * @param tx - The finalized transaction response from blockchain
401
- * @param actionCode - The action code to verify against
402
- * @returns True if the transaction is valid and matches the action code
403
- */
404
- verifyFinalizedTransaction(tx, actionCode) {
405
- try {
406
- // Handle null/undefined transaction
407
- if (tx.transaction === null || tx.transaction === undefined) {
408
- return false;
409
- }
410
- // Both legacy and versioned responses have message and signatures
411
- const response = tx.transaction;
412
- if (!response.message || !response.signatures) {
413
- return false;
414
- }
415
- let transaction;
416
- // Check if it's a versioned transaction by looking at the message structure
417
- if (response.message instanceof web3_js_1.MessageV0) {
418
- // Versioned transaction - reconstruct from message and signatures
419
- transaction = new web3_js_1.VersionedTransaction(response.message);
420
- // Note: In a real scenario, signatures would be attached, but for testing we just need the message
421
- }
422
- else {
423
- // Legacy transaction - reconstruct from compiled message and signatures
424
- const compiledMessage = response.message;
425
- transaction = web3_js_1.Transaction.populate(compiledMessage, response.signatures);
426
- }
427
- const meta = this.decodeMeta(transaction);
428
- if (!meta) {
429
- return false; // No protocol meta found
430
- }
431
- if (!meta.iss) {
432
- return false; // No issuer field in meta
433
- }
434
- if (!actionCode.codeHash) {
435
- return false; // No codeHash available
436
- }
437
- if (!meta.id || meta.id !== actionCode.codeHash) {
438
- return false; // ID doesn't match expected value
439
- }
440
- if (meta.prefix !== actionCode.prefix) {
441
- return false;
442
- }
443
- if (meta.initiator !== actionCode.pubkey) {
444
- return false;
445
- }
446
- let userPubkey = null;
447
- try {
448
- userPubkey = new web3_js_1.PublicKey(actionCode.pubkey);
449
- }
450
- catch (error) {
451
- return false;
452
- }
453
- if (userPubkey) {
454
- if (transaction instanceof web3_js_1.VersionedTransaction) {
455
- const message = transaction.message;
456
- if (message instanceof web3_js_1.MessageV0) {
457
- // Check if user's public key is in the static account keys
458
- const userKeyIndex = message.staticAccountKeys.findIndex(key => key.equals(userPubkey));
459
- if (userKeyIndex === -1) {
460
- return false; // User's key not found in transaction
461
- }
462
- // Check if user's key is a signer (first bit of header indicates signer status)
463
- const isUserSigner = (message.header.numRequiredSignatures > 0) &&
464
- (userKeyIndex < message.header.numRequiredSignatures);
465
- if (!isUserSigner) {
466
- return false; // User didn't sign the transaction
467
- }
468
- }
469
- else {
470
- return false; // Unsupported message type
471
- }
472
- }
473
- else if (transaction instanceof web3_js_1.Transaction) {
474
- // For legacy transactions, check if user's key is in the account keys
475
- const accountKeys = transaction.compileMessage().accountKeys;
476
- const userKeyIndex = accountKeys.findIndex(key => key.equals(userPubkey));
477
- if (userKeyIndex === -1) {
478
- return false; // User's key not found in transaction
479
- }
480
- // Check if user's key is a signer
481
- const isUserSigner = userKeyIndex < transaction.compileMessage().header.numRequiredSignatures;
482
- if (!isUserSigner) {
483
- return false; // User didn't sign the transaction
484
- }
485
- }
486
- else {
487
- return false; // Invalid transaction type
488
- }
489
- }
490
- // 5. Check that tx is signed by protocol (issuer)
491
- if (!this.hasIssuerSignature(transaction, meta.iss)) {
492
- return false; // Protocol didn't sign the transaction
493
- }
494
- // All checks passed
495
- return true;
496
- }
497
- catch (error) {
498
- // If any error occurs during verification, return false
499
- return false;
500
- }
501
- }
502
- /**
503
- * Validate a signed message for sign-only mode
504
- * @param message - The message that was signed
505
- * @param signedMessage - The signed message (base64 or hex)
506
- * @param pubkey - The public key that should have signed the message
507
- * @returns True if the signature is valid
508
- */
509
- validateSignedMessage(message, signedMessage, pubkey) {
510
- try {
511
- // Decode the public key (base58)
512
- const publicKeyBytes = bs58_1.default.decode(pubkey);
513
- // Decode the signature as base58 (Solana convention)
514
- const signature = bs58_1.default.decode(signedMessage);
515
- const messageBuffer = buffer_1.Buffer.from(message, 'utf8');
516
- return nacl.sign.detached.verify(messageBuffer, signature, publicKeyBytes);
517
- }
518
- catch (e) {
519
- return false;
520
- }
521
- }
522
- }
523
- exports.SolanaAdapter = SolanaAdapter;
524
- SolanaAdapter.MEMO_PROGRAM_ID = spl_memo_1.MEMO_PROGRAM_ID;
package/dist/codegen.d.ts DELETED
@@ -1,76 +0,0 @@
1
- export declare class CodeGenerator {
2
- static TIME_WINDOW_MS: number;
3
- static CODE_DIGITS: number;
4
- static MIN_PREFIX_LENGTH: number;
5
- static MAX_PREFIX_LENGTH: number;
6
- /**
7
- * Validate prefix format
8
- * @param prefix - The prefix to validate
9
- * @returns True if prefix is valid, false otherwise
10
- */
11
- static validatePrefix(prefix: string): boolean;
12
- /**
13
- * Validate generated code format (prefix + exactly 8 digits)
14
- * @param code - The code to validate
15
- * @returns True if code is valid, false otherwise
16
- */
17
- static validateCodeFormat(code: string): boolean;
18
- /**
19
- * Validate that the numeric part of a code is exactly 8 digits
20
- * @param code - The code to validate (can include prefix)
21
- * @returns True if numeric part is valid, false otherwise
22
- */
23
- static validateCodeDigits(code: string): boolean;
24
- /**
25
- * Normalize prefix - convert PROTOCOL_CODE_PREFIX to empty string, validate others
26
- * @param prefix - The prefix to normalize
27
- * @returns Normalized prefix
28
- * @throws Error if prefix is invalid
29
- */
30
- static normalizePrefix(prefix: string): string;
31
- /**
32
- * Generate a deterministic 8-digit code based on public key, prefix, and timestamp
33
- * @param pubkey - Solana wallet public key (base58)
34
- * @param prefix - Optional namespace prefix (default: PROTOCOL_CODE_PREFIX)
35
- * @param timestamp - UNIX timestamp in milliseconds (defaults to now)
36
- * @returns Object containing code, issuedAt, and expiresAt timestamps
37
- * @throws Error if generated code is invalid
38
- */
39
- static generateCode(pubkey: string, prefix?: string, timestamp?: number): {
40
- code: string;
41
- issuedAt: number;
42
- expiresAt: number;
43
- };
44
- /**
45
- * Derive the full SHA-256 hash for storage or encryption key generation
46
- * @param pubkey - Solana wallet public key (base58)
47
- * @param prefix - Optional namespace prefix (default: PROTOCOL_CODE_PREFIX)
48
- * @param timestamp - UNIX timestamp in milliseconds (defaults to now)
49
- * @returns Full SHA-256 hash string
50
- */
51
- static deriveCodeHash(pubkey: string, prefix?: string, timestamp?: number): string;
52
- /**
53
- * Get the expected code for a given public key and timestamp
54
- * @param pubkey - Solana wallet public key (base58)
55
- * @param timestamp - UNIX timestamp in milliseconds
56
- * @param prefix - Optional namespace prefix (default: PROTOCOL_CODE_PREFIX)
57
- * @returns Full code string with prefix + 8 digits
58
- */
59
- static getExpectedCode(pubkey: string, timestamp: number, prefix?: string): string;
60
- /**
61
- * Validate if a code matches the expected code for a given public key and timestamp
62
- * @param code - The code to validate (can include prefix)
63
- * @param pubkey - Solana wallet public key (base58)
64
- * @param timestamp - UNIX timestamp in milliseconds
65
- * @param prefix - Optional namespace prefix (default: PROTOCOL_CODE_PREFIX)
66
- * @returns True if code matches expected code and timestamp is valid
67
- */
68
- static validateCode(code: string, pubkey: string, timestamp: number, prefix?: string): boolean;
69
- /**
70
- * Check if a timestamp falls within a valid time window
71
- * @param timestamp - UNIX timestamp in milliseconds
72
- * @returns True if timestamp is valid
73
- */
74
- static isValidTimestamp(timestamp: number): boolean;
75
- }
76
- //# sourceMappingURL=codegen.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"codegen.d.ts","sourceRoot":"","sources":["../src/codegen.ts"],"names":[],"mappings":"AAGA,qBAAa,aAAa;IACtB,MAAM,CAAC,cAAc,SAAY;IACjC,MAAM,CAAC,WAAW,SAAe;IACjC,MAAM,CAAC,iBAAiB,SAAqB;IAC7C,MAAM,CAAC,iBAAiB,SAAqB;IAE7C;;;;OAIG;IACH,MAAM,CAAC,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO;IAM9C;;;;OAIG;IACH,MAAM,CAAC,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAoChD;;;;OAIG;IACH,MAAM,CAAC,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAkChD;;;;;OAKG;IACH,MAAM,CAAC,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM;IAQ9C;;;;;;;OAOG;IACH,MAAM,CAAC,YAAY,CACf,MAAM,EAAE,MAAM,EACd,MAAM,GAAE,MAA6B,EACrC,SAAS,GAAE,MAAmB,GAC/B;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE;IAiCxD;;;;;;OAMG;IACH,MAAM,CAAC,cAAc,CACjB,MAAM,EAAE,MAAM,EACd,MAAM,GAAE,MAA6B,EACrC,SAAS,CAAC,EAAE,MAAM,GACnB,MAAM;IAQT;;;;;;OAMG;IACH,MAAM,CAAC,eAAe,CAClB,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,MAAM,GAAE,MAA6B,GACtC,MAAM;IAIT;;;;;;;OAOG;IACH,MAAM,CAAC,YAAY,CACf,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,MAAM,GAAE,MAA6B,GACtC,OAAO;IAgBV;;;;OAIG;IACH,MAAM,CAAC,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO;CAGtD"}