@heyanon-arp/sdk 0.0.9 → 0.0.11
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.
- package/dist/assets.d.ts +78 -35
- package/dist/escrow/condition-hash.d.ts +10 -4
- package/dist/escrow/create-lock.d.ts +22 -20
- package/dist/escrow/index.d.ts +3 -1
- package/dist/escrow/lifecycle-instructions.d.ts +45 -0
- package/dist/escrow/lock-account.d.ts +48 -0
- package/dist/index.d.ts +1 -3
- package/dist/index.js +226 -267
- package/dist/index.mjs +208 -259
- package/dist/settlement/index.d.ts +0 -2
- package/dist/types/agent.d.ts +0 -6
- package/dist/types/body.d.ts +1 -116
- package/dist/types/envelope.d.ts +10 -36
- package/dist/types/index.d.ts +2 -2
- package/package.json +1 -1
- package/dist/cosignature/cosign.d.ts +0 -35
- package/dist/cosignature/index.d.ts +0 -2
- package/dist/settlement/settlement.d.ts +0 -111
package/dist/index.js
CHANGED
|
@@ -190,56 +190,6 @@ var SETTLEMENT_PURPOSES = [
|
|
|
190
190
|
Purpose.SOLANA_RESOLVE_DISPUTE
|
|
191
191
|
];
|
|
192
192
|
|
|
193
|
-
// src/cosignature/cosign.ts
|
|
194
|
-
var COSIGN_ALLOWED = [Purpose.RECEIPT, Purpose.DISPUTE_RESPONSE];
|
|
195
|
-
function signCosignature(input) {
|
|
196
|
-
const purpose = input.payload.purpose;
|
|
197
|
-
if (!COSIGN_ALLOWED.includes(purpose)) {
|
|
198
|
-
throw new Error(`signCosignature: purpose "${purpose}" is not allowed for co_signature`);
|
|
199
|
-
}
|
|
200
|
-
const digest = sha2.sha256(canonicalBytes(input.payload));
|
|
201
|
-
const sigBytes = sign2(digest, input.identitySecretKey);
|
|
202
|
-
const payload_hash = `sha256:${bytesToHex2(digest)}`;
|
|
203
|
-
const sig = `ed25519:${base.base64.encode(sigBytes)}`;
|
|
204
|
-
return {
|
|
205
|
-
agent_did: input.signerDid,
|
|
206
|
-
purpose,
|
|
207
|
-
payload_hash,
|
|
208
|
-
sig
|
|
209
|
-
};
|
|
210
|
-
}
|
|
211
|
-
function verifyCosignature(input) {
|
|
212
|
-
if (input.cosignature.purpose !== input.payload.purpose) {
|
|
213
|
-
return { ok: false, reason: "purpose_mismatch" };
|
|
214
|
-
}
|
|
215
|
-
const digest = sha2.sha256(canonicalBytes(input.payload));
|
|
216
|
-
const expectedHash = `sha256:${bytesToHex2(digest)}`;
|
|
217
|
-
if (expectedHash !== input.cosignature.payload_hash) {
|
|
218
|
-
return { ok: false, reason: "payload_hash_mismatch" };
|
|
219
|
-
}
|
|
220
|
-
const sigPrefix = "ed25519:";
|
|
221
|
-
if (!input.cosignature.sig.startsWith(sigPrefix)) {
|
|
222
|
-
return { ok: false, reason: "signature_malformed", detail: "sig missing ed25519: prefix" };
|
|
223
|
-
}
|
|
224
|
-
let sigBytes;
|
|
225
|
-
try {
|
|
226
|
-
sigBytes = base.base64.decode(input.cosignature.sig.slice(sigPrefix.length));
|
|
227
|
-
} catch {
|
|
228
|
-
return { ok: false, reason: "signature_malformed", detail: "sig base64 decode failed" };
|
|
229
|
-
}
|
|
230
|
-
if (sigBytes.length !== 64) {
|
|
231
|
-
return { ok: false, reason: "signature_malformed", detail: `expected 64-byte signature, got ${sigBytes.length}` };
|
|
232
|
-
}
|
|
233
|
-
return verify2(sigBytes, digest, input.signerIdentityPubkey) ? { ok: true } : { ok: false, reason: "signature_invalid" };
|
|
234
|
-
}
|
|
235
|
-
function bytesToHex2(b) {
|
|
236
|
-
let s = "";
|
|
237
|
-
for (let i = 0; i < b.length; i++) {
|
|
238
|
-
s += b[i].toString(16).padStart(2, "0");
|
|
239
|
-
}
|
|
240
|
-
return s;
|
|
241
|
-
}
|
|
242
|
-
|
|
243
193
|
// src/challenge/challenge.ts
|
|
244
194
|
var CHALLENGE_PURPOSE_BYTES = new TextEncoder().encode(Purpose.CHALLENGE);
|
|
245
195
|
function buildSigningInput(challengeBytes) {
|
|
@@ -333,7 +283,7 @@ function verifyKeyLinkAttestation(attestation, scryptKey) {
|
|
|
333
283
|
function signedMessageHash(envelope) {
|
|
334
284
|
const input = envelope.attachments === void 0 ? { protected: envelope.protected, body: envelope.body } : { protected: envelope.protected, body: envelope.body, attachments: envelope.attachments };
|
|
335
285
|
const digest = sha2.sha256(canonicalBytes(input));
|
|
336
|
-
return `sha256:${
|
|
286
|
+
return `sha256:${bytesToHex2(digest)}`;
|
|
337
287
|
}
|
|
338
288
|
function serverEventHash(input) {
|
|
339
289
|
const canonicalInput = {
|
|
@@ -344,7 +294,7 @@ function serverEventHash(input) {
|
|
|
344
294
|
sender_signature: input.senderSignature
|
|
345
295
|
};
|
|
346
296
|
const digest = sha2.sha256(canonicalBytes(canonicalInput));
|
|
347
|
-
return `sha256:${
|
|
297
|
+
return `sha256:${bytesToHex2(digest)}`;
|
|
348
298
|
}
|
|
349
299
|
function findFirstChainDivergence(events) {
|
|
350
300
|
for (let i = 0; i < events.length; i++) {
|
|
@@ -361,185 +311,13 @@ function findFirstChainDivergence(events) {
|
|
|
361
311
|
}
|
|
362
312
|
return null;
|
|
363
313
|
}
|
|
364
|
-
function
|
|
314
|
+
function bytesToHex2(b) {
|
|
365
315
|
let s = "";
|
|
366
316
|
for (let i = 0; i < b.length; i++) {
|
|
367
317
|
s += b[i].toString(16).padStart(2, "0");
|
|
368
318
|
}
|
|
369
319
|
return s;
|
|
370
320
|
}
|
|
371
|
-
function deriveLockId(delegationId) {
|
|
372
|
-
const bytes16 = delegationIdToBytes16(delegationId);
|
|
373
|
-
const prefix = new TextEncoder().encode("arp-lock-v1");
|
|
374
|
-
const input = new Uint8Array(prefix.length + 16);
|
|
375
|
-
input.set(prefix, 0);
|
|
376
|
-
input.set(bytes16, prefix.length);
|
|
377
|
-
return sha2.sha256(input);
|
|
378
|
-
}
|
|
379
|
-
var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
|
|
380
|
-
function delegationIdToBytes16(delegationId) {
|
|
381
|
-
const uuid = delegationId.startsWith("del_") ? delegationId.slice(4) : delegationId;
|
|
382
|
-
if (!UUID_RE.test(uuid)) {
|
|
383
|
-
if (delegationId.startsWith("del_")) {
|
|
384
|
-
throw new Error(`Invalid delegation_id UUID (must be canonical lowercase): ${JSON.stringify(uuid)}`);
|
|
385
|
-
}
|
|
386
|
-
throw new Error(`Invalid delegation_id format: expected "del_<uuid>" or bare canonical-lowercase UUID, got ${JSON.stringify(delegationId)}`);
|
|
387
|
-
}
|
|
388
|
-
const hex = uuid.replace(/-/g, "");
|
|
389
|
-
const out = new Uint8Array(16);
|
|
390
|
-
for (let i = 0; i < 16; i++) {
|
|
391
|
-
out[i] = Number.parseInt(hex.substring(i * 2, i * 2 + 2), 16);
|
|
392
|
-
}
|
|
393
|
-
return out;
|
|
394
|
-
}
|
|
395
|
-
function bytes16ToDelegationId(bytes) {
|
|
396
|
-
if (bytes.length !== 16) {
|
|
397
|
-
throw new Error(`bytes16ToDelegationId: expected 16 bytes, got ${bytes.length}`);
|
|
398
|
-
}
|
|
399
|
-
const hex = Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
|
|
400
|
-
return `del_${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20, 32)}`;
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
// src/settlement/settlement.ts
|
|
404
|
-
var PURPOSE_RELEASE_STRING = "ARP-SOLANA-RELEASE-v1.5";
|
|
405
|
-
var PURPOSE_PARTIAL_RELEASE_STRING = "ARP-SOLANA-PARTIAL-RELEASE-v1.5";
|
|
406
|
-
var PURPOSE_REFUND_STRING = "ARP-SOLANA-REFUND-v1";
|
|
407
|
-
var PURPOSE_RELEASE = new TextEncoder().encode(PURPOSE_RELEASE_STRING);
|
|
408
|
-
var PURPOSE_PARTIAL_RELEASE = new TextEncoder().encode(PURPOSE_PARTIAL_RELEASE_STRING);
|
|
409
|
-
var PURPOSE_REFUND = new TextEncoder().encode(PURPOSE_REFUND_STRING);
|
|
410
|
-
var ZERO_PUBKEY = new Uint8Array(32);
|
|
411
|
-
function buildReleaseDigest(input) {
|
|
412
|
-
requireLen(input.programId, 32, "programId");
|
|
413
|
-
requireLen(input.lockId, 32, "lockId");
|
|
414
|
-
requireLen(input.payerSettlementPubkey, 32, "payerSettlementPubkey");
|
|
415
|
-
requireLen(input.payeeSettlementPubkey, 32, "payeeSettlementPubkey");
|
|
416
|
-
requireLen(input.mint, 32, "mint");
|
|
417
|
-
requireLen(input.conditionHash, 32, "conditionHash");
|
|
418
|
-
requireLen(input.receiptEventHash, 32, "receiptEventHash");
|
|
419
|
-
requireLen(input.deliverableHash, 32, "deliverableHash");
|
|
420
|
-
const feeBps = input.feeBpsAtLock ?? 0;
|
|
421
|
-
requireFeeBps(feeBps);
|
|
422
|
-
const feeRecipient = input.feeRecipientAtLock ?? ZERO_PUBKEY;
|
|
423
|
-
requireLen(feeRecipient, 32, "feeRecipientAtLock");
|
|
424
|
-
const delegationBytes = delegationIdToBytes16(input.delegationId);
|
|
425
|
-
const buf = concatBytes(
|
|
426
|
-
PURPOSE_RELEASE,
|
|
427
|
-
new Uint8Array([input.clusterTag]),
|
|
428
|
-
input.programId,
|
|
429
|
-
input.lockId,
|
|
430
|
-
input.payerSettlementPubkey,
|
|
431
|
-
input.payeeSettlementPubkey,
|
|
432
|
-
input.mint,
|
|
433
|
-
u64LE(input.amount),
|
|
434
|
-
input.conditionHash,
|
|
435
|
-
delegationBytes,
|
|
436
|
-
input.receiptEventHash,
|
|
437
|
-
input.deliverableHash,
|
|
438
|
-
u64LE(input.expiresAt),
|
|
439
|
-
u16LE(feeBps),
|
|
440
|
-
feeRecipient
|
|
441
|
-
);
|
|
442
|
-
return sha2.sha256(buf);
|
|
443
|
-
}
|
|
444
|
-
function buildPartialReleaseDigest(input) {
|
|
445
|
-
requireLen(input.programId, 32, "programId");
|
|
446
|
-
requireLen(input.lockId, 32, "lockId");
|
|
447
|
-
requireLen(input.payerSettlementPubkey, 32, "payerSettlementPubkey");
|
|
448
|
-
requireLen(input.payeeSettlementPubkey, 32, "payeeSettlementPubkey");
|
|
449
|
-
requireLen(input.mint, 32, "mint");
|
|
450
|
-
requireLen(input.conditionHash, 32, "conditionHash");
|
|
451
|
-
requireLen(input.receiptEventHash, 32, "receiptEventHash");
|
|
452
|
-
requireLen(input.deliverableHash, 32, "deliverableHash");
|
|
453
|
-
const feeBps = input.feeBpsAtLock ?? 0;
|
|
454
|
-
requireFeeBps(feeBps);
|
|
455
|
-
const feeRecipient = input.feeRecipientAtLock ?? ZERO_PUBKEY;
|
|
456
|
-
requireLen(feeRecipient, 32, "feeRecipientAtLock");
|
|
457
|
-
const delegationBytes = delegationIdToBytes16(input.delegationId);
|
|
458
|
-
const buf = concatBytes(
|
|
459
|
-
PURPOSE_PARTIAL_RELEASE,
|
|
460
|
-
new Uint8Array([input.clusterTag]),
|
|
461
|
-
input.programId,
|
|
462
|
-
input.lockId,
|
|
463
|
-
input.payerSettlementPubkey,
|
|
464
|
-
input.payeeSettlementPubkey,
|
|
465
|
-
input.mint,
|
|
466
|
-
u64LE(input.amount),
|
|
467
|
-
u64LE(input.payeeAmount),
|
|
468
|
-
input.conditionHash,
|
|
469
|
-
delegationBytes,
|
|
470
|
-
input.receiptEventHash,
|
|
471
|
-
input.deliverableHash,
|
|
472
|
-
u64LE(input.expiresAt),
|
|
473
|
-
u16LE(feeBps),
|
|
474
|
-
feeRecipient
|
|
475
|
-
);
|
|
476
|
-
return sha2.sha256(buf);
|
|
477
|
-
}
|
|
478
|
-
var REFUND_REASON_BYTES = {
|
|
479
|
-
expired: 0,
|
|
480
|
-
dispute_resolution: 1,
|
|
481
|
-
payer_cancellation: 2,
|
|
482
|
-
both_parties_agreed: 3
|
|
483
|
-
};
|
|
484
|
-
function buildRefundDigest(input) {
|
|
485
|
-
requireLen(input.programId, 32, "programId");
|
|
486
|
-
requireLen(input.lockId, 32, "lockId");
|
|
487
|
-
requireLen(input.payerSettlementPubkey, 32, "payerSettlementPubkey");
|
|
488
|
-
requireLen(input.payeeSettlementPubkey, 32, "payeeSettlementPubkey");
|
|
489
|
-
requireLen(input.mint, 32, "mint");
|
|
490
|
-
const buf = concatBytes(
|
|
491
|
-
PURPOSE_REFUND,
|
|
492
|
-
new Uint8Array([input.clusterTag]),
|
|
493
|
-
input.programId,
|
|
494
|
-
input.lockId,
|
|
495
|
-
input.payerSettlementPubkey,
|
|
496
|
-
input.payeeSettlementPubkey,
|
|
497
|
-
input.mint,
|
|
498
|
-
u64LE(input.amount),
|
|
499
|
-
new Uint8Array([input.reasonByte]),
|
|
500
|
-
u64LE(input.expiresAt)
|
|
501
|
-
);
|
|
502
|
-
return sha2.sha256(buf);
|
|
503
|
-
}
|
|
504
|
-
function requireLen(bytes, expected, name) {
|
|
505
|
-
if (bytes.length !== expected) {
|
|
506
|
-
throw new Error(`settlement digest: ${name} must be ${expected} bytes, got ${bytes.length}`);
|
|
507
|
-
}
|
|
508
|
-
}
|
|
509
|
-
function requireFeeBps(bps) {
|
|
510
|
-
if (!Number.isInteger(bps) || bps < 0 || bps > 65535) {
|
|
511
|
-
throw new Error(`settlement digest: feeBpsAtLock must be a u16 (0..65535), got ${bps}`);
|
|
512
|
-
}
|
|
513
|
-
}
|
|
514
|
-
function concatBytes(...parts) {
|
|
515
|
-
let total = 0;
|
|
516
|
-
for (const p of parts) total += p.length;
|
|
517
|
-
const out = new Uint8Array(total);
|
|
518
|
-
let off = 0;
|
|
519
|
-
for (const p of parts) {
|
|
520
|
-
out.set(p, off);
|
|
521
|
-
off += p.length;
|
|
522
|
-
}
|
|
523
|
-
return out;
|
|
524
|
-
}
|
|
525
|
-
function u64LE(value) {
|
|
526
|
-
if (value < 0n || value > 0xffffffffffffffffn) {
|
|
527
|
-
throw new Error(`settlement digest: u64 value out of range: ${value}`);
|
|
528
|
-
}
|
|
529
|
-
const out = new Uint8Array(8);
|
|
530
|
-
let v = value;
|
|
531
|
-
for (let i = 0; i < 8; i++) {
|
|
532
|
-
out[i] = Number(v & 0xffn);
|
|
533
|
-
v >>= 8n;
|
|
534
|
-
}
|
|
535
|
-
return out;
|
|
536
|
-
}
|
|
537
|
-
function u16LE(value) {
|
|
538
|
-
const out = new Uint8Array(2);
|
|
539
|
-
out[0] = value & 255;
|
|
540
|
-
out[1] = value >> 8 & 255;
|
|
541
|
-
return out;
|
|
542
|
-
}
|
|
543
321
|
|
|
544
322
|
// src/settlement/token-program.ts
|
|
545
323
|
var SPL_TOKEN_PROGRAM_ID_BASE58 = "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA";
|
|
@@ -658,32 +436,73 @@ var SOLANA_CLUSTER_IDS = {
|
|
|
658
436
|
"solana-devnet": "EtWTRABZaYq6iMfeYKouRu166VU2xqa1"
|
|
659
437
|
};
|
|
660
438
|
var SLIP44_SOLANA = 501;
|
|
439
|
+
var MAINNET_MINTS = {
|
|
440
|
+
USDC: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
|
|
441
|
+
USDT: "Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB",
|
|
442
|
+
ANON: "9McvH6w97oewLmPxqQEoHUAv3u5iYMyQ9AeZZhguYf1T"
|
|
443
|
+
};
|
|
444
|
+
var DEVNET_MINTS = {
|
|
445
|
+
USDC: "7ZjP2eJnQrW1SuE1kAP7tdrQuhkTVpco1NQKGjEMHpgg"
|
|
446
|
+
};
|
|
661
447
|
var USDC_MINTS = {
|
|
662
|
-
"solana-mainnet":
|
|
663
|
-
"solana-devnet":
|
|
448
|
+
"solana-mainnet": MAINNET_MINTS.USDC,
|
|
449
|
+
"solana-devnet": DEVNET_MINTS.USDC
|
|
664
450
|
};
|
|
665
|
-
var
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
symbol: "USDC"
|
|
670
|
-
},
|
|
671
|
-
"USDC:solana-devnet": {
|
|
672
|
-
asset_id: `solana:${SOLANA_CLUSTER_IDS["solana-devnet"]}/spl:${USDC_MINTS["solana-devnet"]}`,
|
|
673
|
-
decimals: 6,
|
|
674
|
-
symbol: "USDC"
|
|
675
|
-
},
|
|
676
|
-
"SOL:solana-mainnet": {
|
|
677
|
-
asset_id: `solana:${SOLANA_CLUSTER_IDS["solana-mainnet"]}/slip44:${SLIP44_SOLANA}`,
|
|
678
|
-
decimals: 9,
|
|
679
|
-
symbol: "SOL"
|
|
680
|
-
},
|
|
681
|
-
"SOL:solana-devnet": {
|
|
682
|
-
asset_id: `solana:${SOLANA_CLUSTER_IDS["solana-devnet"]}/slip44:${SLIP44_SOLANA}`,
|
|
683
|
-
decimals: 9,
|
|
684
|
-
symbol: "SOL"
|
|
685
|
-
}
|
|
451
|
+
var SOL_MAINNET = {
|
|
452
|
+
asset_id: `solana:${SOLANA_CLUSTER_IDS["solana-mainnet"]}/slip44:${SLIP44_SOLANA}`,
|
|
453
|
+
decimals: 9,
|
|
454
|
+
symbol: "SOL"
|
|
686
455
|
};
|
|
456
|
+
var SOL_DEVNET = {
|
|
457
|
+
asset_id: `solana:${SOLANA_CLUSTER_IDS["solana-devnet"]}/slip44:${SLIP44_SOLANA}`,
|
|
458
|
+
decimals: 9,
|
|
459
|
+
symbol: "SOL"
|
|
460
|
+
};
|
|
461
|
+
var USDC_DEVNET = {
|
|
462
|
+
asset_id: `solana:${SOLANA_CLUSTER_IDS["solana-devnet"]}/spl:${DEVNET_MINTS.USDC}`,
|
|
463
|
+
decimals: 9,
|
|
464
|
+
symbol: "USDC"
|
|
465
|
+
};
|
|
466
|
+
var ASSET_WHITELIST = {
|
|
467
|
+
"solana-mainnet": [
|
|
468
|
+
SOL_MAINNET,
|
|
469
|
+
{
|
|
470
|
+
asset_id: `solana:${SOLANA_CLUSTER_IDS["solana-mainnet"]}/spl:${MAINNET_MINTS.USDC}`,
|
|
471
|
+
decimals: 6,
|
|
472
|
+
symbol: "USDC"
|
|
473
|
+
},
|
|
474
|
+
{
|
|
475
|
+
asset_id: `solana:${SOLANA_CLUSTER_IDS["solana-mainnet"]}/spl:${MAINNET_MINTS.USDT}`,
|
|
476
|
+
decimals: 6,
|
|
477
|
+
symbol: "USDT"
|
|
478
|
+
},
|
|
479
|
+
{
|
|
480
|
+
asset_id: `solana:${SOLANA_CLUSTER_IDS["solana-mainnet"]}/spl:${MAINNET_MINTS.ANON}`,
|
|
481
|
+
decimals: 9,
|
|
482
|
+
symbol: "ANON"
|
|
483
|
+
}
|
|
484
|
+
],
|
|
485
|
+
"solana-devnet": [SOL_DEVNET, USDC_DEVNET]
|
|
486
|
+
};
|
|
487
|
+
var WELL_KNOWN_ASSETS = Object.fromEntries(
|
|
488
|
+
Object.entries(ASSET_WHITELIST).flatMap(([cluster, assets]) => assets.map((asset) => [`${asset.symbol}:${cluster}`, asset]))
|
|
489
|
+
);
|
|
490
|
+
var WELL_KNOWN_ASSET_KEYS = Object.keys(WELL_KNOWN_ASSETS);
|
|
491
|
+
function listWhitelistedAssets(cluster) {
|
|
492
|
+
return ASSET_WHITELIST[cluster].map((a) => ({ ...a }));
|
|
493
|
+
}
|
|
494
|
+
function findAssetByAssetId(assetId) {
|
|
495
|
+
for (const [cluster, assets] of Object.entries(ASSET_WHITELIST)) {
|
|
496
|
+
const asset = assets.find((a) => a.asset_id === assetId);
|
|
497
|
+
if (asset) return { asset: { ...asset }, cluster, key: `${asset.symbol}:${cluster}` };
|
|
498
|
+
}
|
|
499
|
+
return null;
|
|
500
|
+
}
|
|
501
|
+
function isWhitelistedAssetId(assetId, cluster) {
|
|
502
|
+
const hit = findAssetByAssetId(assetId);
|
|
503
|
+
if (!hit) return false;
|
|
504
|
+
return cluster === void 0 || hit.cluster === cluster;
|
|
505
|
+
}
|
|
687
506
|
var CAIP19_REGEX = /^[-a-z0-9]{3,8}:[-_a-zA-Z0-9]{1,32}\/[-a-z0-9]{3,8}:[-.%a-zA-Z0-9]{1,128}$/;
|
|
688
507
|
function isAssetIdentifier(value) {
|
|
689
508
|
if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
|
|
@@ -697,22 +516,54 @@ function resolveAsset(input) {
|
|
|
697
516
|
const hit = WELL_KNOWN_ASSETS[input];
|
|
698
517
|
if (hit) return { ...hit };
|
|
699
518
|
if (CAIP19_REGEX.test(input)) {
|
|
519
|
+
const whitelisted = findAssetByAssetId(input);
|
|
520
|
+
if (whitelisted) return whitelisted.asset;
|
|
700
521
|
return { asset_id: input, decimals: NaN };
|
|
701
522
|
}
|
|
702
523
|
return null;
|
|
703
524
|
}
|
|
704
|
-
|
|
525
|
+
function deriveLockId(delegationId) {
|
|
526
|
+
const bytes16 = delegationIdToBytes16(delegationId);
|
|
527
|
+
const prefix = new TextEncoder().encode("arp-lock-v1");
|
|
528
|
+
const input = new Uint8Array(prefix.length + 16);
|
|
529
|
+
input.set(prefix, 0);
|
|
530
|
+
input.set(bytes16, prefix.length);
|
|
531
|
+
return sha2.sha256(input);
|
|
532
|
+
}
|
|
533
|
+
var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
|
|
534
|
+
function delegationIdToBytes16(delegationId) {
|
|
535
|
+
const uuid = delegationId.startsWith("del_") ? delegationId.slice(4) : delegationId;
|
|
536
|
+
if (!UUID_RE.test(uuid)) {
|
|
537
|
+
if (delegationId.startsWith("del_")) {
|
|
538
|
+
throw new Error(`Invalid delegation_id UUID (must be canonical lowercase): ${JSON.stringify(uuid)}`);
|
|
539
|
+
}
|
|
540
|
+
throw new Error(`Invalid delegation_id format: expected "del_<uuid>" or bare canonical-lowercase UUID, got ${JSON.stringify(delegationId)}`);
|
|
541
|
+
}
|
|
542
|
+
const hex = uuid.replace(/-/g, "");
|
|
543
|
+
const out = new Uint8Array(16);
|
|
544
|
+
for (let i = 0; i < 16; i++) {
|
|
545
|
+
out[i] = Number.parseInt(hex.substring(i * 2, i * 2 + 2), 16);
|
|
546
|
+
}
|
|
547
|
+
return out;
|
|
548
|
+
}
|
|
549
|
+
function bytes16ToDelegationId(bytes) {
|
|
550
|
+
if (bytes.length !== 16) {
|
|
551
|
+
throw new Error(`bytes16ToDelegationId: expected 16 bytes, got ${bytes.length}`);
|
|
552
|
+
}
|
|
553
|
+
const hex = Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
|
|
554
|
+
return `del_${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20, 32)}`;
|
|
555
|
+
}
|
|
705
556
|
function deriveDelegationConditionHash(delegation) {
|
|
706
|
-
const required = ["delegationId", "scopeSummary"
|
|
557
|
+
const required = ["delegationId", "scopeSummary"];
|
|
707
558
|
for (const field of required) {
|
|
708
559
|
if (delegation[field] === void 0) {
|
|
709
560
|
throw new Error(`deriveDelegationConditionHash: required field '${String(field)}' is missing from the delegation input`);
|
|
710
561
|
}
|
|
711
562
|
}
|
|
712
563
|
const subset = {
|
|
564
|
+
v: "arp-condition-v2",
|
|
713
565
|
delegationId: delegation.delegationId,
|
|
714
|
-
scopeSummary: delegation.scopeSummary
|
|
715
|
-
pricingModel: delegation.pricingModel
|
|
566
|
+
scopeSummary: delegation.scopeSummary
|
|
716
567
|
};
|
|
717
568
|
if (delegation.currency !== void 0) subset.currency = delegation.currency;
|
|
718
569
|
const bytes = canonicalBytes(subset);
|
|
@@ -741,15 +592,16 @@ function parseCaip19SolanaAssetId(assetId) {
|
|
|
741
592
|
throw new Error(`Unsupported CAIP-19 namespace: ${JSON.stringify(namespaceRaw)} (only 'spl' and 'slip44' are supported on Solana)`);
|
|
742
593
|
}
|
|
743
594
|
var CREATE_LOCK_DISCRIMINATOR = new Uint8Array([171, 216, 92, 167, 165, 8, 153, 90]);
|
|
744
|
-
|
|
595
|
+
var CREATE_LOCK_NATIVE_DISCRIMINATOR = new Uint8Array([234, 19, 218, 36, 23, 74, 218, 108]);
|
|
596
|
+
function buildCreateLockIxData(args, opts = {}) {
|
|
745
597
|
if (args.lockId.length !== 32) throw new Error("create_lock: lockId must be 32 bytes");
|
|
746
598
|
if (args.conditionHash.length !== 32) throw new Error("create_lock: conditionHash must be 32 bytes");
|
|
747
599
|
requireU64(args.amount, "amount");
|
|
748
|
-
|
|
749
|
-
const total = 8 + 32 + 8 + 32
|
|
600
|
+
const disc = opts.native ? CREATE_LOCK_NATIVE_DISCRIMINATOR : CREATE_LOCK_DISCRIMINATOR;
|
|
601
|
+
const total = 8 + 32 + 8 + 32;
|
|
750
602
|
const out = new Uint8Array(total);
|
|
751
603
|
let off = 0;
|
|
752
|
-
out.set(
|
|
604
|
+
out.set(disc, off);
|
|
753
605
|
off += 8;
|
|
754
606
|
out.set(args.lockId, off);
|
|
755
607
|
off += 32;
|
|
@@ -757,8 +609,6 @@ function buildCreateLockIxData(args) {
|
|
|
757
609
|
off += 8;
|
|
758
610
|
out.set(args.conditionHash, off);
|
|
759
611
|
off += 32;
|
|
760
|
-
writeU64LE(out, off, args.expiry);
|
|
761
|
-
off += 8;
|
|
762
612
|
if (off !== total) throw new Error(`create_lock ix data layout drift: ${off} != ${total}`);
|
|
763
613
|
return out;
|
|
764
614
|
}
|
|
@@ -778,17 +628,123 @@ function computeCreateLockDiscriminator() {
|
|
|
778
628
|
const h = sha2.sha256(new TextEncoder().encode("global:create_lock"));
|
|
779
629
|
return h.slice(0, 8);
|
|
780
630
|
}
|
|
631
|
+
var ESCROW_PDA_SEEDS = {
|
|
632
|
+
LOCK: "lock",
|
|
633
|
+
ESCROW: "escrow",
|
|
634
|
+
CONFIG: "config",
|
|
635
|
+
STAKE_VAULT: "stake_vault",
|
|
636
|
+
COLLATERAL: "collateral",
|
|
637
|
+
DISPUTE_RESOLUTION: "dispute_resolution",
|
|
638
|
+
OPERATOR_AUTH: "operator_auth",
|
|
639
|
+
EVENT_AUTHORITY: "__event_authority"
|
|
640
|
+
};
|
|
641
|
+
var NO_ARG_LIFECYCLE_INSTRUCTIONS = [
|
|
642
|
+
"accept_lock",
|
|
643
|
+
"submit_work",
|
|
644
|
+
"claim_work_payment",
|
|
645
|
+
"claim_work_payment_native",
|
|
646
|
+
"cancel_lock",
|
|
647
|
+
"cancel_lock_native",
|
|
648
|
+
"claim_expired_work",
|
|
649
|
+
"claim_expired_work_native",
|
|
650
|
+
"open_dispute",
|
|
651
|
+
"close_dispute",
|
|
652
|
+
"close_dispute_native"
|
|
653
|
+
];
|
|
654
|
+
function instructionDiscriminator(ixName) {
|
|
655
|
+
return sha2.sha256(new TextEncoder().encode(`global:${ixName}`)).slice(0, 8);
|
|
656
|
+
}
|
|
657
|
+
function buildLifecycleIxData(ixName) {
|
|
658
|
+
if (!NO_ARG_LIFECYCLE_INSTRUCTIONS.includes(ixName)) {
|
|
659
|
+
throw new Error(`buildLifecycleIxData: '${ixName}' is not a no-arg lifecycle instruction`);
|
|
660
|
+
}
|
|
661
|
+
return instructionDiscriminator(ixName);
|
|
662
|
+
}
|
|
663
|
+
function buildResolveDisputeIxData(args, opts = {}) {
|
|
664
|
+
if (args.reasonHash.length !== 32) throw new Error("resolve_dispute: reasonHash must be 32 bytes");
|
|
665
|
+
if (args.disputeId.length !== 16) throw new Error("resolve_dispute: disputeId must be 16 bytes");
|
|
666
|
+
const disc = instructionDiscriminator(opts.native ? "resolve_dispute_native" : "resolve_dispute");
|
|
667
|
+
const total = 8 + 1 + 32 + 16;
|
|
668
|
+
const out = new Uint8Array(total);
|
|
669
|
+
out.set(disc, 0);
|
|
670
|
+
out[8] = args.isPayerWinner ? 1 : 0;
|
|
671
|
+
out.set(args.reasonHash, 9);
|
|
672
|
+
out.set(args.disputeId, 41);
|
|
673
|
+
return out;
|
|
674
|
+
}
|
|
675
|
+
var LOCK_ACCOUNT_SIZE = 269;
|
|
676
|
+
var LOCK_ACCOUNT_DISCRIMINATOR = new Uint8Array([8, 255, 36, 202, 210, 22, 57, 137]);
|
|
677
|
+
var LOCK_STATE_NAMES = ["created", "canceled", "in_progress", "submitted", "paid", "revoked", "disputing", "dispute_resolved", "dispute_closed"];
|
|
678
|
+
var LOCK_TERMINAL_STATES = ["canceled", "paid", "revoked", "dispute_resolved", "dispute_closed"];
|
|
679
|
+
var NATIVE_SOL_MINT_BASE58 = "11111111111111111111111111111111";
|
|
680
|
+
function decodeLockAccount(data) {
|
|
681
|
+
if (data.length !== LOCK_ACCOUNT_SIZE) {
|
|
682
|
+
throw new Error(`decodeLockAccount: expected ${LOCK_ACCOUNT_SIZE} bytes, got ${data.length}`);
|
|
683
|
+
}
|
|
684
|
+
for (let i = 0; i < 8; i++) {
|
|
685
|
+
if (data[i] !== LOCK_ACCOUNT_DISCRIMINATOR[i]) {
|
|
686
|
+
throw new Error("decodeLockAccount: account discriminator is not Lock");
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
const stateByte = data[185];
|
|
690
|
+
const state = LOCK_STATE_NAMES[stateByte];
|
|
691
|
+
if (state === void 0) {
|
|
692
|
+
throw new Error(`decodeLockAccount: unknown LockState discriminant ${stateByte}`);
|
|
693
|
+
}
|
|
694
|
+
const mint = base.base58.encode(data.slice(113, 145));
|
|
695
|
+
return {
|
|
696
|
+
lockId: toHex(data.subarray(8, 40)),
|
|
697
|
+
version: data[40],
|
|
698
|
+
payer: base.base58.encode(data.slice(41, 73)),
|
|
699
|
+
payee: base.base58.encode(data.slice(73, 105)),
|
|
700
|
+
amount: readU64LE(data, 105),
|
|
701
|
+
mint,
|
|
702
|
+
isNative: mint === NATIVE_SOL_MINT_BASE58,
|
|
703
|
+
conditionHash: toHex(data.subarray(145, 177)),
|
|
704
|
+
expiry: readU64LE(data, 177),
|
|
705
|
+
state,
|
|
706
|
+
stateByte,
|
|
707
|
+
feeBpsAtLock: data[186] | data[187] << 8,
|
|
708
|
+
feeRecipientAtLock: base.base58.encode(data.slice(188, 220)),
|
|
709
|
+
workerStakeAtLock: readU64LE(data, 220),
|
|
710
|
+
operatorDisputeFeeAtLock: readU64LE(data, 228),
|
|
711
|
+
treasuryAtLock: base.base58.encode(data.slice(236, 268)),
|
|
712
|
+
bump: data[268]
|
|
713
|
+
};
|
|
714
|
+
}
|
|
715
|
+
function computeLockAccountDiscriminator() {
|
|
716
|
+
return sha2.sha256(new TextEncoder().encode("account:Lock")).slice(0, 8);
|
|
717
|
+
}
|
|
718
|
+
function toHex(bytes) {
|
|
719
|
+
let hex = "";
|
|
720
|
+
for (const b of bytes) hex += b.toString(16).padStart(2, "0");
|
|
721
|
+
return hex;
|
|
722
|
+
}
|
|
723
|
+
function readU64LE(buf, off) {
|
|
724
|
+
let v = 0n;
|
|
725
|
+
for (let i = 0; i < 8; i++) {
|
|
726
|
+
v |= BigInt(buf[off + i]) << BigInt(8 * i);
|
|
727
|
+
}
|
|
728
|
+
return v;
|
|
729
|
+
}
|
|
781
730
|
|
|
731
|
+
exports.ASSET_WHITELIST = ASSET_WHITELIST;
|
|
782
732
|
exports.CAIP19_REGEX = CAIP19_REGEX;
|
|
783
733
|
exports.COSIGNATURE_PURPOSES = COSIGNATURE_PURPOSES;
|
|
784
734
|
exports.CREATE_LOCK_DISCRIMINATOR = CREATE_LOCK_DISCRIMINATOR;
|
|
735
|
+
exports.CREATE_LOCK_NATIVE_DISCRIMINATOR = CREATE_LOCK_NATIVE_DISCRIMINATOR;
|
|
785
736
|
exports.DECLINE_REASONS = DECLINE_REASONS;
|
|
737
|
+
exports.DEVNET_MINTS = DEVNET_MINTS;
|
|
738
|
+
exports.ESCROW_PDA_SEEDS = ESCROW_PDA_SEEDS;
|
|
739
|
+
exports.LOCK_ACCOUNT_DISCRIMINATOR = LOCK_ACCOUNT_DISCRIMINATOR;
|
|
740
|
+
exports.LOCK_ACCOUNT_SIZE = LOCK_ACCOUNT_SIZE;
|
|
741
|
+
exports.LOCK_STATE_NAMES = LOCK_STATE_NAMES;
|
|
742
|
+
exports.LOCK_TERMINAL_STATES = LOCK_TERMINAL_STATES;
|
|
743
|
+
exports.MAINNET_MINTS = MAINNET_MINTS;
|
|
744
|
+
exports.NATIVE_SOL_MINT_BASE58 = NATIVE_SOL_MINT_BASE58;
|
|
745
|
+
exports.NO_ARG_LIFECYCLE_INSTRUCTIONS = NO_ARG_LIFECYCLE_INSTRUCTIONS;
|
|
786
746
|
exports.PROTECTED_PURPOSES = PROTECTED_PURPOSES;
|
|
787
|
-
exports.PURPOSE_PARTIAL_RELEASE_STRING = PURPOSE_PARTIAL_RELEASE_STRING;
|
|
788
|
-
exports.PURPOSE_REFUND_STRING = PURPOSE_REFUND_STRING;
|
|
789
|
-
exports.PURPOSE_RELEASE_STRING = PURPOSE_RELEASE_STRING;
|
|
790
747
|
exports.Purpose = Purpose;
|
|
791
|
-
exports.REFUND_REASON_BYTES = REFUND_REASON_BYTES;
|
|
792
748
|
exports.SCRYPT_PARAMS = SCRYPT_PARAMS;
|
|
793
749
|
exports.SETTLEMENT_PURPOSES = SETTLEMENT_PURPOSES;
|
|
794
750
|
exports.SLIP44_SOLANA = SLIP44_SOLANA;
|
|
@@ -800,14 +756,15 @@ exports.WELL_KNOWN_ASSET_KEYS = WELL_KNOWN_ASSET_KEYS;
|
|
|
800
756
|
exports.base58btcDecode = base58btcDecode;
|
|
801
757
|
exports.base58btcEncode = base58btcEncode;
|
|
802
758
|
exports.buildCreateLockIxData = buildCreateLockIxData;
|
|
803
|
-
exports.
|
|
804
|
-
exports.
|
|
805
|
-
exports.buildReleaseDigest = buildReleaseDigest;
|
|
759
|
+
exports.buildLifecycleIxData = buildLifecycleIxData;
|
|
760
|
+
exports.buildResolveDisputeIxData = buildResolveDisputeIxData;
|
|
806
761
|
exports.bytes16ToDelegationId = bytes16ToDelegationId;
|
|
807
762
|
exports.canonicalBytes = canonicalBytes;
|
|
808
763
|
exports.canonicalJson = canonicalJson;
|
|
809
764
|
exports.canonicalSha256Hex = canonicalSha256Hex;
|
|
810
765
|
exports.computeCreateLockDiscriminator = computeCreateLockDiscriminator;
|
|
766
|
+
exports.computeLockAccountDiscriminator = computeLockAccountDiscriminator;
|
|
767
|
+
exports.decodeLockAccount = decodeLockAccount;
|
|
811
768
|
exports.delegationIdToBytes16 = delegationIdToBytes16;
|
|
812
769
|
exports.deriveDelegationConditionHash = deriveDelegationConditionHash;
|
|
813
770
|
exports.deriveLockId = deriveLockId;
|
|
@@ -815,13 +772,17 @@ exports.deriveScryptKey = deriveScryptKey;
|
|
|
815
772
|
exports.detectTokenProgramFromOwner = detectTokenProgramFromOwner;
|
|
816
773
|
exports.detectTokenProgramFromOwnerBytes = detectTokenProgramFromOwnerBytes;
|
|
817
774
|
exports.expiresAt = expiresAt;
|
|
775
|
+
exports.findAssetByAssetId = findAssetByAssetId;
|
|
818
776
|
exports.findFirstChainDivergence = findFirstChainDivergence;
|
|
819
777
|
exports.formatDid = formatDid;
|
|
820
778
|
exports.generateKeyPair = generateKeyPair;
|
|
821
779
|
exports.getPublicKey = getPublicKey2;
|
|
780
|
+
exports.instructionDiscriminator = instructionDiscriminator;
|
|
822
781
|
exports.isAssetIdentifier = isAssetIdentifier;
|
|
823
782
|
exports.isDeclineReason = isDeclineReason;
|
|
824
783
|
exports.isValidDid = isValidDid;
|
|
784
|
+
exports.isWhitelistedAssetId = isWhitelistedAssetId;
|
|
785
|
+
exports.listWhitelistedAssets = listWhitelistedAssets;
|
|
825
786
|
exports.parseCaip19SolanaAssetId = parseCaip19SolanaAssetId;
|
|
826
787
|
exports.parseDid = parseDid;
|
|
827
788
|
exports.pollUntil = pollUntil;
|
|
@@ -833,13 +794,11 @@ exports.senderNonce = senderNonce;
|
|
|
833
794
|
exports.serverEventHash = serverEventHash;
|
|
834
795
|
exports.sign = sign2;
|
|
835
796
|
exports.signChallenge = signChallenge;
|
|
836
|
-
exports.signCosignature = signCosignature;
|
|
837
797
|
exports.signEnvelope = signEnvelope;
|
|
838
798
|
exports.signKeyLinkAttestation = signKeyLinkAttestation;
|
|
839
799
|
exports.signedMessageHash = signedMessageHash;
|
|
840
800
|
exports.uuidV4 = uuidV4;
|
|
841
801
|
exports.verify = verify2;
|
|
842
802
|
exports.verifyChallenge = verifyChallenge;
|
|
843
|
-
exports.verifyCosignature = verifyCosignature;
|
|
844
803
|
exports.verifyEnvelope = verifyEnvelope;
|
|
845
804
|
exports.verifyKeyLinkAttestation = verifyKeyLinkAttestation;
|