@actioncodes/protocol 2.0.22 → 2.0.23

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 (79) hide show
  1. package/README.md +239 -146
  2. package/docs/ActionCodesProtocol/README.md +2 -2
  3. package/docs/ActionCodesProtocol/classes/ActionCodesProtocol.md +183 -33
  4. package/docs/README.md +425 -8
  5. package/docs/adapters/BaseChainAdapter/README.md +3 -4
  6. package/docs/adapters/BaseChainAdapter/classes/BaseChainAdapter.md +87 -20
  7. package/docs/adapters/BaseChainAdapter/interfaces/ChainAdapter.md +68 -12
  8. package/docs/adapters/BaseChainAdapter/type-aliases/SignFn.md +25 -0
  9. package/docs/adapters/SolanaAdapter/README.md +6 -3
  10. package/docs/adapters/SolanaAdapter/classes/SolanaAdapter.md +140 -43
  11. package/docs/adapters/SolanaAdapter/type-aliases/SolanaTransaction.md +3 -3
  12. package/docs/adapters/SolanaAdapter/variables/ADAPTER_CHAIN_NAME.md +11 -0
  13. package/docs/constants/README.md +2 -2
  14. package/docs/constants/variables/CODE_CHARSET_DIGITS.md +2 -2
  15. package/docs/constants/variables/CODE_DEFAULT_LENGTH.md +2 -2
  16. package/docs/constants/variables/CODE_MAX_LENGTH.md +2 -2
  17. package/docs/constants/variables/CODE_MIN_LENGTH.md +2 -2
  18. package/docs/constants/variables/PROTOCOL_META_MAX_BYTES.md +3 -3
  19. package/docs/constants/variables/PROTOCOL_NORMALIZATION.md +2 -2
  20. package/docs/constants/variables/SUPPORTED_CHAINS.md +9 -3
  21. package/docs/errors/README.md +4 -2
  22. package/docs/errors/classes/ExpiredCodeError.md +85 -21
  23. package/docs/errors/classes/InvalidAdapterError.md +751 -0
  24. package/docs/errors/classes/InvalidCodeFormatError.md +85 -21
  25. package/docs/errors/classes/InvalidPubkeyFormatError.md +85 -21
  26. package/docs/errors/classes/InvalidSignatureError.md +85 -21
  27. package/docs/errors/classes/MetaMismatchError.md +85 -21
  28. package/docs/errors/classes/MissingMetaError.md +85 -21
  29. package/docs/errors/classes/ProtocolError.md +75 -21
  30. package/docs/errors/classes/TransactionNotSignedByIntendedOwnerError.md +85 -21
  31. package/docs/errors/classes/TransactionNotSignedByIssuerError.md +755 -0
  32. package/docs/errors/enumerations/ProtocolErrorCode.md +39 -15
  33. package/docs/index/README.md +170 -14
  34. package/docs/modules.md +3 -3
  35. package/docs/strategy/DelegationStrategy/README.md +11 -0
  36. package/docs/strategy/DelegationStrategy/classes/DelegationStrategy.md +79 -0
  37. package/docs/strategy/WalletStrategy/README.md +2 -2
  38. package/docs/strategy/WalletStrategy/classes/WalletStrategy.md +22 -18
  39. package/docs/types/README.md +11 -3
  40. package/docs/types/interfaces/ActionCode.md +23 -26
  41. package/docs/types/interfaces/ActionCodeRevoke.md +93 -0
  42. package/docs/types/interfaces/CanonicalMessageParts.md +5 -13
  43. package/docs/types/interfaces/CanonicalRevokeMessageParts.md +33 -0
  44. package/docs/types/interfaces/CodeGenerationConfig.md +6 -6
  45. package/docs/types/interfaces/DelegatedActionCode.md +97 -0
  46. package/docs/types/interfaces/DelegatedActionCodeRevoke.md +105 -0
  47. package/docs/types/interfaces/DelegationProof.md +49 -0
  48. package/docs/types/type-aliases/Chain.md +11 -0
  49. package/docs/utils/canonical/README.md +6 -2
  50. package/docs/utils/canonical/functions/getCanonicalMessageParts.md +21 -0
  51. package/docs/utils/canonical/functions/serializeCanonical.md +3 -3
  52. package/docs/utils/canonical/functions/serializeCanonicalRevoke.md +21 -0
  53. package/docs/utils/canonical/functions/serializeDelegationProof.md +21 -0
  54. package/docs/utils/canonical/variables/CANONICAL_MESSAGE_PREFIX.md +3 -3
  55. package/docs/utils/canonical/variables/CANONICAL_MESSAGE_VERSION.md +3 -3
  56. package/docs/utils/canonical/variables/CANONICAL_REVOKE_MESSAGE_PREFIX.md +11 -0
  57. package/docs/utils/crypto/README.md +2 -3
  58. package/docs/utils/crypto/functions/base32EncodeCrockford.md +2 -2
  59. package/docs/utils/crypto/functions/codeHash.md +2 -2
  60. package/docs/utils/crypto/functions/digestToDigits.md +2 -2
  61. package/docs/utils/crypto/functions/hkdfSha256.md +2 -2
  62. package/docs/utils/crypto/functions/hmacSha256.md +2 -2
  63. package/docs/utils/crypto/functions/sha256.md +2 -2
  64. package/docs/utils/crypto/functions/truncateBits.md +2 -2
  65. package/docs/utils/protocolMeta/README.md +2 -2
  66. package/docs/utils/protocolMeta/functions/buildProtocolMeta.md +3 -3
  67. package/docs/utils/protocolMeta/functions/parseProtocolMeta.md +3 -3
  68. package/docs/utils/protocolMeta/functions/validateProtocolMetaFormat.md +3 -3
  69. package/docs/utils/protocolMeta/interfaces/ProtocolMetaFields.md +11 -3
  70. package/docs/utils/protocolMeta/variables/SCHEME.md +3 -3
  71. package/package.json +7 -7
  72. package/docs/adapters/BaseChainAdapter/interfaces/BaseContext.md +0 -17
  73. package/docs/adapters/BaseChainAdapter/type-aliases/ChainContext.md +0 -23
  74. package/docs/adapters/NodeCryptoAdapter/README.md +0 -15
  75. package/docs/adapters/NodeCryptoAdapter/classes/NodeCryptoAdapter.md +0 -254
  76. package/docs/adapters/NodeCryptoAdapter/type-aliases/NodeCryptoContext.md +0 -27
  77. package/docs/adapters/SolanaAdapter/type-aliases/SolanaContext.md +0 -27
  78. package/docs/types/interfaces/CodeGenerationResult.md +0 -25
  79. package/docs/utils/crypto/functions/generateRandomSecret.md +0 -15
package/README.md CHANGED
@@ -5,9 +5,10 @@ Instead of heavy signature popups or complex flows, it uses short-lived one-time
5
5
 
6
6
  ### This enables:
7
7
  - Secure intent binding – the code is cryptographically tied to a wallet/public key.
8
- - Fast verification – relayers/servers can validate in microseconds.
9
- - Cross-chain support – adapters handle chain-specific quirks (currently we are supporting Solana)
8
+ - Fast verification – relayers/servers can validate in microseconds (~3ms per verification).
9
+ - Cross-chain support – adapters handle chain-specific quirks (currently supporting Solana)
10
10
  - Simple dev UX – just generate → sign → verify.
11
+ - Issuer support – allows separation between code issuer and intent owner for advanced use cases.
11
12
 
12
13
  ### What's new in v2 (compared to [v1](https://github.com/otaprotocol/actioncodes))
13
14
  - Now we use Bun as core library. We are down to ~3ms per code signature verification on commodity hardware.
@@ -16,7 +17,7 @@ Instead of heavy signature popups or complex flows, it uses short-lived one-time
16
17
  - Chain Adapters simplified → They don't enforce business rules; they just provide utilities:
17
18
  - createProtocolMetaIx (for attaching metadata)
18
19
  - parseMeta / verifyTransactionMatchesCode (for checking integrity)
19
- - verifyTransactionSignedByIntentOwner (optional stronger guarantee).
20
+ - verifyTransactionSignedByIntentOwner (checks both `int` and `iss` signatures when present).
20
21
  - Errors are typed → Clear ProtocolError.* categories instead of generic fails.
21
22
 
22
23
  ### Core Concepts
@@ -27,7 +28,9 @@ Instead of heavy signature popups or complex flows, it uses short-lived one-time
27
28
 
28
29
  2. Protocol Meta
29
30
  - The "payload" carried with transactions to tie them to action codes.
30
- - Versioned, deterministic, size-limited.
31
+ - Versioned, deterministic, size-limited (max 512 bytes).
32
+ - Fields: `ver` (version), `id` (code hash), `int` (intent owner), `iss` (issuer, optional), `p` (params, optional).
33
+ - When `iss` field is present, both issuer and intent owner must sign the transaction.
31
34
  - Perfect for attaching to transactions or off-chain messages for tracing.
32
35
 
33
36
  3. Canonical Message
@@ -45,137 +48,159 @@ The **Wallet Strategy** is the simplest approach where codes are generated direc
45
48
 
46
49
  #### How it works:
47
50
  ```typescript
48
- // 1. Get canonical message for signing
49
- const canonicalMessage = protocol.getCanonicalMessageParts("user-wallet-address");
51
+ import { ActionCodesProtocol } from '@actioncodes/protocol';
52
+ import { SolanaAdapter } from '@actioncodes/protocol';
50
53
 
51
- // 2. Sign the canonical message with user's wallet
52
- const signature = await userWallet.signMessage(canonicalMessage);
54
+ // Initialize protocol
55
+ const protocol = new ActionCodesProtocol({
56
+ codeLength: 8, // Code length (6-24 digits)
57
+ ttlMs: 120000, // Time to live (2 minutes)
58
+ clockSkewMs: 5000 // Clock skew tolerance (5 seconds)
59
+ });
53
60
 
54
- // 3. Generate code with the signed canonical message (secret is optional)
55
- const result = await protocol.generateCode("wallet", canonicalMessage, signature);
56
- // Optional: provide secret for enhanced security
57
- // const result = await protocol.generateCode("wallet", canonicalMessage, signature, "optional-secret");
61
+ // Register Solana adapter
62
+ protocol.registerAdapter('solana', new SolanaAdapter());
58
63
 
59
- // 4. Validate code
60
- const isValid = await protocol.validateCode("wallet", result.actionCode, {
61
- chain: "solana",
62
- pubkey: "user-wallet-address",
63
- signature: signature
64
- });
64
+ // 1. Generate code with wallet strategy
65
+ const signFn = async (message: Uint8Array, chain: string) => {
66
+ // Sign the canonical message with user's wallet
67
+ const signature = await userWallet.signMessage(message);
68
+ return signature; // Returns base58-encoded signature
69
+ };
70
+
71
+ const actionCode = await protocol.generate(
72
+ "wallet",
73
+ userWallet.publicKey.toString(),
74
+ "solana",
75
+ signFn
76
+ );
77
+
78
+ // 2. Validate code
79
+ protocol.validate("wallet", actionCode);
80
+ // Throws ProtocolError if validation fails
65
81
  ```
66
82
 
67
83
  #### Key Features:
68
84
  - **Signature-based security** - Codes require a valid signature over the canonical message (prevents public key + timestamp attacks)
69
85
  - **Direct wallet binding** - Codes are cryptographically tied to the user's public key
70
- - **Optional secrets** - Users can provide a secret for enhanced security (uses HMAC), or omit it (uses SHA256)
86
+ - **HMAC-based generation** - Uses signature as entropy source for secure code generation
71
87
  - **Immediate validation** - No delegation certificates needed
72
- - **Perfect for** - Direct user interactions, simple authentication flows
88
+ - **Perfect for** - Direct user interactions, simple authentication flows, transaction authorization
73
89
 
74
90
  #### Security Model:
75
91
  - **Signature verification** - All codes require a valid signature over the canonical message
76
92
  - **Public key + timestamp attack prevention** - Signatures prevent attackers from generating codes with just public key + timestamp
77
- - Codes are bound to the specific public key
78
- - Optional secret provides additional entropy (HMAC vs SHA256)
93
+ - **HMAC-based entropy** - Codes use HMAC-SHA256 with signature as key, ensuring cryptographic security
94
+ - Codes are bound to the specific public key and timestamp
79
95
  - Time-based expiration prevents replay attacks
80
96
  - Canonical message signing ensures integrity
81
97
 
82
98
  ### 2. Delegation Strategy (Advanced)
83
99
 
84
- The **Delegation Strategy** allows users to pre-authorize actions through delegation certificates, enabling more complex workflows like relayer services.
100
+ The **Delegation Strategy** allows users to pre-authorize actions through delegation proofs, enabling more complex workflows like relayer services.
85
101
 
86
102
  #### How it works:
87
103
 
88
- ##### Step 1: Create Delegation Certificate
104
+ ##### Step 1: Create Delegation Proof
89
105
  ```typescript
90
- // User creates a delegation certificate template
91
- const template = await protocol.createDelegationCertificateTemplate(
92
- userPublicKey,
93
- 3600000, // 1 hour expiration
94
- "solana"
95
- );
106
+ import { serializeDelegationProof } from '@actioncodes/protocol';
96
107
 
97
- // User signs the certificate
98
- const message = DelegationStrategy.serializeCertificate(template);
99
- const signature = await userWallet.signMessage(message);
100
-
101
- const certificate: DelegationCertificate = {
102
- ...template,
103
- signature: signature
108
+ // User creates a delegation proof
109
+ const delegationProof = {
110
+ walletPubkey: userWallet.publicKey.toString(),
111
+ delegatedPubkey: delegatedKeypair.publicKey.toString(),
112
+ chain: "solana",
113
+ expiresAt: Date.now() + 3600000, // 1 hour expiration
114
+ signature: "" // Will be set after signing
104
115
  };
116
+
117
+ // User signs the delegation proof
118
+ const delegationMessage = serializeDelegationProof(delegationProof);
119
+ const delegationSignature = await userWallet.signMessage(delegationMessage);
120
+ delegationProof.signature = delegationSignature;
105
121
  ```
106
122
 
107
123
  ##### Step 2: Generate Delegated Codes
108
124
  ```typescript
109
- // Generate codes using the delegation certificate
110
- const result = await protocol.generateCode("delegation", certificate);
111
- const actionCode = result.actionCode;
125
+ // Sign function for delegated keypair
126
+ const delegatedSignFn = async (message: Uint8Array, chain: string) => {
127
+ const signature = await delegatedKeypair.signMessage(message);
128
+ return signature;
129
+ };
130
+
131
+ // Generate code using delegation strategy
132
+ const delegatedActionCode = await protocol.generate(
133
+ "delegation",
134
+ delegationProof,
135
+ "solana",
136
+ delegatedSignFn
137
+ );
112
138
  ```
113
139
 
114
140
  ##### Step 3: Validate Delegated Codes
115
141
  ```typescript
116
- // Validate the delegated code with the certificate
117
- const isValid = await protocol.validateCode(actionCode, "delegation", certificate);
142
+ // Validate the delegated code
143
+ protocol.validate("delegation", delegatedActionCode);
144
+ // Throws ProtocolError if validation fails
118
145
  ```
119
146
 
120
147
  #### Key Features:
121
148
  - **Pre-authorization** - Users can authorize actions for a limited time
122
149
  - **Relayer support** - Third parties can validate codes without generating them
123
- - **Certificate-based** - Codes are bound to specific delegation certificates
124
- - **Time-limited** - Certificates have expiration times
150
+ - **Proof-based** - Codes are bound to specific delegation proofs
151
+ - **Time-limited** - Delegation proofs have expiration times
125
152
  - **Perfect for** - Relayer services, automated systems, complex workflows
126
153
 
127
154
  #### Security Model:
128
- - **Code-Certificate Binding** - Codes are cryptographically bound to their specific certificate
129
- - **Signature Verification** - Certificate signatures are verified using chain adapters
130
- - **Delegation ID** - Each certificate has a unique ID derived from its content + signature
131
- - **Cross-Certificate Protection** - Codes from one certificate cannot be used with another
132
- - **Relayer Security** - Relayers can validate codes but cannot generate them without the user's signature
155
+ - **Code-Proof Binding** - Codes are cryptographically bound to their specific delegation proof
156
+ - **Signature Verification** - Delegation proof signatures are verified using chain adapters
157
+ - **Dual Signature Requirement** - Both wallet signature (on proof) and delegated signature (on code) are required
158
+ - **Cross-Proof Protection** - Codes from one delegation proof cannot be used with another
159
+ - **Relayer Security** - Relayers can validate codes but cannot generate them without the delegated keypair's signature
133
160
 
134
161
  #### Important Security Guarantees:
135
162
 
136
- 1. **Stolen Delegation IDs are Useless**
137
- - Delegation IDs are public identifiers (like transaction hashes)
138
- - They cannot be used to generate or validate codes
139
- - They're safe to share publicly
163
+ 1. **Stolen Delegation Proofs are Limited**
164
+ - Delegation proofs contain public data (pubkeys, expiration, chain)
165
+ - They cannot be used to generate codes without the delegated keypair's private key
166
+ - The proof signature prevents tampering but doesn't enable code generation
140
167
 
141
168
  2. **Stolen Signatures Cannot Create Valid Codes**
142
169
  - Even if an attacker steals a signature, they cannot create valid codes
143
- - Codes are bound to the ENTIRE certificate (not just the signature)
144
- - Different certificate data = different code = validation failure
170
+ - Codes are bound to the ENTIRE delegation proof (not just the signature)
171
+ - Different proof data = different code = validation failure
145
172
 
146
173
  3. **Relayer Code Generation Prevention**
147
- - Relayers cannot generate codes even with public certificate data
148
- - Certificate hashes include the signature (private user asset)
149
- - Only the original user can generate valid codes
174
+ - Relayers cannot generate codes even with public delegation proof data
175
+ - Codes require signatures from the delegated keypair (private asset)
176
+ - Only holders of the delegated keypair can generate valid codes
150
177
 
151
- 4. **Code-Certificate Binding**
152
- - Codes are cryptographically linked to their specific certificate
153
- - Cross-certificate attacks are impossible
154
- - Each certificate produces unique codes
178
+ 4. **Code-Proof Binding**
179
+ - Codes are cryptographically linked to their specific delegation proof
180
+ - Cross-proof attacks are impossible
181
+ - Each delegation proof produces unique codes
155
182
 
156
- #### Delegation Certificate Structure:
183
+ #### Delegation Proof Structure:
157
184
  ```typescript
158
- interface DelegationCertificate {
159
- version: "1.0";
160
- delegator: string; // User's public key
161
- issuedAt: number; // Timestamp when issued
162
- expiresAt: number; // Expiration timestamp
163
- nonce: string; // Unique nonce for this certificate
164
- chain: string; // Target blockchain
165
- signature: string; // User's signature of the certificate
185
+ interface DelegationProof {
186
+ walletPubkey: string; // Original wallet's public key
187
+ delegatedPubkey: string; // Delegated keypair's public key
188
+ chain: string; // Target blockchain
189
+ expiresAt: number; // Expiration timestamp
190
+ signature: string; // Wallet's signature of the delegation proof
166
191
  }
167
192
  ```
168
193
 
169
194
  #### Delegated Action Code Structure:
170
195
  ```typescript
171
196
  interface DelegatedActionCode {
172
- code: string; // The actual action code
173
- pubkey: string; // User's public key
174
- timestamp: number; // Generation timestamp
175
- expiresAt: number; // Code expiration
176
- delegationId: string; // Hash of the certificate (used internally as secret)
177
- delegatedBy: string; // Who delegated (same as pubkey)
178
- // Note: secret field is inherited from ActionCode but not used in delegation
197
+ code: string; // The actual action code
198
+ pubkey: string; // Delegated pubkey (who signs the code)
199
+ timestamp: number; // Generation timestamp
200
+ expiresAt: number; // Code expiration
201
+ signature: string; // Signature from delegated keypair
202
+ chain: string; // Target blockchain
203
+ delegationProof: DelegationProof; // The delegation proof
179
204
  }
180
205
  ```
181
206
 
@@ -186,72 +211,106 @@ interface DelegatedActionCode {
186
211
  #### 1. Simple Authentication
187
212
  ```typescript
188
213
  // User logs into a dApp
189
- const canonicalMessage = protocol.getCanonicalMessageParts(userWallet.publicKey);
190
- const signature = await userWallet.signMessage(canonicalMessage);
191
- const result = await protocol.generateCode("wallet", canonicalMessage, signature);
214
+ const signFn = async (message: Uint8Array, chain: string) => {
215
+ return await userWallet.signMessage(message);
216
+ };
217
+
218
+ const actionCode = await protocol.generate(
219
+ "wallet",
220
+ userWallet.publicKey.toString(),
221
+ "solana",
222
+ signFn
223
+ );
192
224
 
193
225
  // dApp validates the code
194
- const isValid = await protocol.validateCode('wallet', result.actionCode, {
195
- chain: "solana",
196
- pubkey: userWallet.publicKey,
197
- signature: signature
198
- });
226
+ protocol.validate("wallet", actionCode);
199
227
  ```
200
228
 
201
229
  #### 2. Transaction Authorization
202
230
  ```typescript
231
+ import { buildProtocolMeta, codeHash } from '@actioncodes/protocol';
232
+
203
233
  // User authorizes a specific transaction
204
- const canonicalMessage = protocol.getCanonicalMessageParts(userWallet.publicKey);
205
- const signature = await userWallet.signMessage(canonicalMessage);
206
- const result = await protocol.generateCode("wallet", canonicalMessage, signature);
207
- // Optional: add secret for enhanced security
208
- // const result = await protocol.generateCode("wallet", canonicalMessage, signature, `tx-${transactionHash}`);
234
+ const signFn = async (message: Uint8Array, chain: string) => {
235
+ return await userWallet.signMessage(message);
236
+ };
237
+
238
+ const actionCode = await protocol.generate(
239
+ "wallet",
240
+ userWallet.publicKey.toString(),
241
+ "solana",
242
+ signFn
243
+ );
209
244
 
210
245
  // Relayer validates before executing
211
- const isValid = await protocol.validateCode('wallet', result.actionCode, {
212
- chain: "solana",
213
- pubkey: userWallet.publicKey,
214
- signature: signature
246
+ protocol.validate("wallet", actionCode);
247
+
248
+ // Attach protocol meta to transaction
249
+ const adapter = protocol.getAdapter("solana") as SolanaAdapter;
250
+ const meta = buildProtocolMeta({
251
+ ver: 2,
252
+ id: codeHash(actionCode.code),
253
+ int: actionCode.pubkey,
215
254
  });
255
+ const txWithMeta = SolanaAdapter.attachProtocolMeta(transactionBase64, meta);
256
+
257
+ // Verify transaction is signed by the intended owner
258
+ adapter.verifyTransactionSignedByIntentOwner(txWithMeta);
216
259
  ```
217
260
 
218
261
  ### Delegation Strategy Use Cases
219
262
 
220
263
  #### 1. Relayer Services
221
264
  ```typescript
222
- // User pre-authorizes a relayer for 1 hour
223
- const certificate = await createDelegationCertificate(userWallet, 3600000);
265
+ // User creates delegation proof for relayer
266
+ const delegationProof = {
267
+ walletPubkey: userWallet.publicKey.toString(),
268
+ delegatedPubkey: relayerKeypair.publicKey.toString(),
269
+ chain: "solana",
270
+ expiresAt: Date.now() + 3600000, // 1 hour
271
+ signature: await signDelegationProof(delegationProof)
272
+ };
224
273
 
225
274
  // Relayer can validate codes but not generate them
226
- const relayer = new RelayerService();
227
- relayer.registerCertificate(certificate);
228
-
229
275
  // User generates codes that relayer can validate
230
- const actionCode = await protocol.generateCode("delegation", certificate);
231
- const isValid = relayer.validateCode(actionCode, certificate);
276
+ const delegatedSignFn = async (message: Uint8Array, chain: string) => {
277
+ return await relayerKeypair.signMessage(message);
278
+ };
279
+
280
+ const actionCode = await protocol.generate(
281
+ "delegation",
282
+ delegationProof,
283
+ "solana",
284
+ delegatedSignFn
285
+ );
286
+
287
+ // Relayer validates the code
288
+ protocol.validate("delegation", actionCode);
232
289
  ```
233
290
 
234
291
  #### 2. Automated Trading Bots
235
292
  ```typescript
236
- // User authorizes trading bot for specific operations
237
- const tradingCertificate = await createDelegationCertificate(userWallet, 86400000); // 24 hours
293
+ // User authorizes trading bot for 24 hours
294
+ const delegationProof = {
295
+ walletPubkey: userWallet.publicKey.toString(),
296
+ delegatedPubkey: botKeypair.publicKey.toString(),
297
+ chain: "solana",
298
+ expiresAt: Date.now() + 86400000, // 24 hours
299
+ signature: await signDelegationProof(delegationProof)
300
+ };
238
301
 
239
- // Bot can execute trades using delegated codes
240
- const tradeCode = await protocol.generateCode("delegation", tradingCertificate);
241
- // Bot executes trade with this code
242
- ```
302
+ // Bot generates codes using delegated keypair
303
+ const botSignFn = async (message: Uint8Array, chain: string) => {
304
+ return await botKeypair.signMessage(message);
305
+ };
243
306
 
244
- #### 3. Multi-Signature Workflows
245
- ```typescript
246
- // Multiple users can delegate to a shared certificate
247
- const sharedCertificate = await createSharedDelegationCertificate([
248
- user1Wallet,
249
- user2Wallet,
250
- user3Wallet
251
- ]);
252
-
253
- // Any authorized user can generate codes
254
- const actionCode = await protocol.generateCode("delegation", sharedCertificate);
307
+ const tradeCode = await protocol.generate(
308
+ "delegation",
309
+ delegationProof,
310
+ "solana",
311
+ botSignFn
312
+ );
313
+ // Bot executes trade with this code
255
314
  ```
256
315
 
257
316
  ## Security Considerations
@@ -271,32 +330,37 @@ const actionCode = await protocol.generateCode("delegation", sharedCertificate);
271
330
  - Cannot be reused
272
331
 
273
332
  4. **Delegation Security**
274
- - Delegation certificates are cryptographically signed
275
- - Codes are bound to specific certificates
276
- - Cross-certificate attacks are impossible
333
+ - Delegation proofs are cryptographically signed
334
+ - Codes are bound to specific delegation proofs
335
+ - Cross-proof attacks are impossible
277
336
 
278
337
  ### Best Practices
279
338
 
280
- 1. **Secret Management**
281
- - Use cryptographically secure random secrets
282
- - Don't reuse secrets across different contexts
283
- - Consider using deterministic secrets based on context
284
-
285
- 2. **Certificate Expiration**
286
- - Set appropriate expiration times for delegation certificates
339
+ 1. **Delegation Proof Expiration**
340
+ - Set appropriate expiration times for delegation proofs
287
341
  - Shorter expiration = higher security
288
342
  - Longer expiration = better UX
289
343
 
290
- 3. **Relayer Security**
291
- - Only trust relayers with full certificates
344
+ 2. **Relayer Security**
345
+ - Only trust relayers with valid delegation proofs
292
346
  - Never share private keys with relayers
293
347
  - Monitor relayer behavior
294
348
 
349
+ 3. **Issuer Field Usage**
350
+ - Use `iss` field when issuer and intent owner are different entities
351
+ - Ensure both signatures are present when `iss` is specified
352
+ - Omit `iss` when it's the same as `int` to save space
353
+
295
354
  4. **Code Validation**
296
355
  - Always validate codes server-side
297
356
  - Check expiration times
298
357
  - Verify the binding to the correct public key
299
358
 
359
+ 5. **Protocol Meta with Issuer**
360
+ - Use `iss` field when issuer differs from intent owner
361
+ - When `iss` is present, ensure transaction is signed by both
362
+ - If `iss` equals `int`, it's automatically omitted (optimization)
363
+
300
364
  ## Performance
301
365
 
302
366
  - **Code Generation**: ~1ms per code
@@ -312,29 +376,58 @@ npm install @actioncodes/protocol
312
376
 
313
377
  # Basic usage
314
378
  import { ActionCodesProtocol } from '@actioncodes/protocol';
379
+ import { SolanaAdapter } from '@actioncodes/protocol';
315
380
 
316
- const protocol = new ActionCodesProtocol();
381
+ // Initialize protocol
382
+ const protocol = new ActionCodesProtocol({
383
+ codeLength: 8, // Code length (6-24 digits)
384
+ ttlMs: 120000, // Time to live (2 minutes)
385
+ clockSkewMs: 5000 // Clock skew tolerance (5 seconds)
386
+ });
317
387
 
318
- // 1. Get canonical message for signing
319
- const canonicalMessage = protocol.getCanonicalMessageParts("your-public-key");
388
+ // Register Solana adapter
389
+ protocol.registerAdapter('solana', new SolanaAdapter());
320
390
 
321
- // 2. Sign the canonical message with your wallet
322
- const signature = await yourWallet.signMessage(canonicalMessage);
391
+ // 1. Sign function for wallet
392
+ const signFn = async (message: Uint8Array, chain: string) => {
393
+ // Sign the canonical message with your wallet
394
+ const signature = await yourWallet.signMessage(message);
395
+ return signature; // Returns base58-encoded signature
396
+ };
323
397
 
324
- // 3. Generate a code with the signed canonical message
325
- const result = await protocol.generateCode("wallet", canonicalMessage, signature);
326
- // Optional: add secret for enhanced security
327
- // const result = await protocol.generateCode("wallet", canonicalMessage, signature, "optional-secret");
398
+ // 2. Generate a code
399
+ const actionCode = await protocol.generate(
400
+ "wallet",
401
+ yourWallet.publicKey.toString(),
402
+ "solana",
403
+ signFn
404
+ );
328
405
 
329
- // 4. Validate a code
330
- const isValid = await protocol.validateCode("wallet", result.actionCode, {
331
- chain: "solana",
332
- pubkey: "your-public-key",
333
- signature: signature
406
+ // 3. Validate a code
407
+ protocol.validate("wallet", actionCode);
408
+ // Throws ProtocolError if validation fails
409
+ ```
410
+
411
+ ### Protocol Meta with Issuer Field
412
+
413
+ When you need to separate the issuer (who created the code) from the intent owner (who will use it):
414
+
415
+ ```typescript
416
+ import { buildProtocolMeta } from '@actioncodes/protocol';
417
+
418
+ // Create protocol meta with issuer
419
+ const meta = buildProtocolMeta({
420
+ ver: 2,
421
+ id: codeHash(actionCode.code),
422
+ int: intentOwnerPubkey, // Who will use the code
423
+ iss: issuerPubkey, // Who issued the code (optional)
334
424
  });
425
+
426
+ // If iss is same as int, it's automatically omitted to save space
427
+ // If iss is present, transaction must be signed by BOTH int and iss
335
428
  ```
336
429
 
337
430
  #### Vision
338
431
 
339
- Action Codes Protocol aim to be the OTP protocol for blockchains but allowing more than authentication: a simple, universal interaction layer usable across apps, chains, and eventually banks/CBDCs.
432
+ Action Codes Protocol aim to be the OTP protocol for blockchains but allowing more than authentication: a simple, universal interaction layer usable across apps, chains, and eventually banks/CBDCs interacting with blockchains.
340
433
 
@@ -1,8 +1,8 @@
1
- [**@actioncodes/protocol-v2**](../README.md)
1
+ [**@actioncodes/protocol**](../README.md)
2
2
 
3
3
  ***
4
4
 
5
- [@actioncodes/protocol-v2](../modules.md) / ActionCodesProtocol
5
+ [@actioncodes/protocol](../modules.md) / ActionCodesProtocol
6
6
 
7
7
  # ActionCodesProtocol
8
8