@atumlabs/mppx-atum-escrow 0.2.2 → 0.3.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.
- package/CHANGELOG.md +18 -0
- package/README.md +211 -46
- package/dist/{chunk-NEM3HEZW.js → chunk-4YD6566T.js} +125 -7
- package/dist/{chunk-4P34CLTO.js → chunk-Z3AUNEU5.js} +63 -5
- package/dist/{chunk-IPZJXELQ.js → chunk-ZFA5SSUP.js} +254 -84
- package/dist/client.d.ts +14 -12
- package/dist/client.js +4 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +19 -3
- package/dist/{internal-DzEGXm14.d.ts → internal-9tB7y-A7.d.ts} +19 -1
- package/dist/server.d.ts +221 -12
- package/dist/server.js +18 -2
- package/package.json +1 -1
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { createRequire as __atumCreateRequire } from 'module'; const require = __atumCreateRequire(import.meta.url);
|
|
2
2
|
import {
|
|
3
|
+
INTENT_ID_META_KEY,
|
|
3
4
|
__commonJS,
|
|
4
5
|
__esm,
|
|
5
6
|
__export,
|
|
@@ -9,9 +10,12 @@ import {
|
|
|
9
10
|
assetIdentifier,
|
|
10
11
|
atumEscrowChargeMethod,
|
|
11
12
|
chainDefaultsFromExtra,
|
|
13
|
+
chargeRequestId,
|
|
14
|
+
intentIdOf,
|
|
12
15
|
namespaceOf,
|
|
13
|
-
require_dist
|
|
14
|
-
|
|
16
|
+
require_dist,
|
|
17
|
+
require_dist2
|
|
18
|
+
} from "./chunk-Z3AUNEU5.js";
|
|
15
19
|
|
|
16
20
|
// ../node_modules/.pnpm/delayed-stream@1.0.0/node_modules/delayed-stream/lib/delayed_stream.js
|
|
17
21
|
var require_delayed_stream = __commonJS({
|
|
@@ -15185,7 +15189,7 @@ var require_axios = __commonJS({
|
|
|
15185
15189
|
});
|
|
15186
15190
|
|
|
15187
15191
|
// ../payment-gateway-client/dist/index.js
|
|
15188
|
-
var
|
|
15192
|
+
var require_dist3 = __commonJS({
|
|
15189
15193
|
"../payment-gateway-client/dist/index.js"(exports, module) {
|
|
15190
15194
|
"use strict";
|
|
15191
15195
|
var __create = Object.create;
|
|
@@ -15380,7 +15384,7 @@ var require_dist2 = __commonJS({
|
|
|
15380
15384
|
}
|
|
15381
15385
|
}
|
|
15382
15386
|
});
|
|
15383
|
-
var
|
|
15387
|
+
var require_dist4 = __commonJS2({
|
|
15384
15388
|
"../contracts/tvm/escrow-encoding/typescript/dist/index.js"(exports2) {
|
|
15385
15389
|
"use strict";
|
|
15386
15390
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
@@ -15423,12 +15427,14 @@ var require_dist2 = __commonJS({
|
|
|
15423
15427
|
"../schemas/declarations/PaymentRequest/v1/bindings/typescript/sender-auth/dist/utils.js"(exports2) {
|
|
15424
15428
|
"use strict";
|
|
15425
15429
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
15426
|
-
exports2.SOLANA_REPLAY_SLOTS = exports2.PERMIT_NONCE_DOMAIN = exports2.REPLAY_HORIZON_SECS = void 0;
|
|
15430
|
+
exports2.REQUEST_ID_DOMAIN = exports2.SOLANA_REPLAY_SLOTS = exports2.PERMIT_NONCE_DOMAIN = exports2.REPLAY_HORIZON_SECS = void 0;
|
|
15427
15431
|
exports2.resolvePermitDeadline = resolvePermitDeadline;
|
|
15428
15432
|
exports2.generatePermitNonce = generatePermitNonce;
|
|
15429
15433
|
exports2.resolvePermitNonce = resolvePermitNonce;
|
|
15434
|
+
exports2.canonicalDepositor = canonicalDepositor2;
|
|
15430
15435
|
exports2.deterministicPermitNonce = deterministicPermitNonce2;
|
|
15431
15436
|
exports2.deterministicSolanaNonce = deterministicSolanaNonce2;
|
|
15437
|
+
exports2.deterministicRequestId = deterministicRequestId;
|
|
15432
15438
|
exports2.sameAddress = sameAddress;
|
|
15433
15439
|
exports2.assertKeyMatchesSender = assertKeyMatchesSender2;
|
|
15434
15440
|
exports2.assertToken = assertToken;
|
|
@@ -15454,7 +15460,7 @@ var require_dist2 = __commonJS({
|
|
|
15454
15460
|
exports2.PERMIT_NONCE_DOMAIN = "atum-permit:v1:";
|
|
15455
15461
|
exports2.SOLANA_REPLAY_SLOTS = 235n;
|
|
15456
15462
|
var SOLANA_BUCKET_BITS = 17n;
|
|
15457
|
-
function
|
|
15463
|
+
function canonicalDepositor2(depositor) {
|
|
15458
15464
|
const lower = depositor.toLowerCase();
|
|
15459
15465
|
return lower.startsWith("0x") ? lower : depositor;
|
|
15460
15466
|
}
|
|
@@ -15462,7 +15468,7 @@ var require_dist2 = __commonJS({
|
|
|
15462
15468
|
if (!requestId) {
|
|
15463
15469
|
throw new Error("sender_auth: request_id is required to derive a deterministic permit nonce");
|
|
15464
15470
|
}
|
|
15465
|
-
return BigInt((0, ethers_1.keccak256)((0, ethers_1.toUtf8Bytes)(`${exports2.PERMIT_NONCE_DOMAIN}${requestId}:${
|
|
15471
|
+
return BigInt((0, ethers_1.keccak256)((0, ethers_1.toUtf8Bytes)(`${exports2.PERMIT_NONCE_DOMAIN}${requestId}:${canonicalDepositor2(depositor)}`)));
|
|
15466
15472
|
}
|
|
15467
15473
|
function deterministicPermitNonce2(params) {
|
|
15468
15474
|
return permitNonceSeed(params.requestId, params.depositor);
|
|
@@ -15473,6 +15479,20 @@ var require_dist2 = __commonJS({
|
|
|
15473
15479
|
const bucket = (seed >> 8n) % (1n << SOLANA_BUCKET_BITS);
|
|
15474
15480
|
return bucket << 32n | slot;
|
|
15475
15481
|
}
|
|
15482
|
+
exports2.REQUEST_ID_DOMAIN = "atum-request:v1:";
|
|
15483
|
+
function deterministicRequestId(params) {
|
|
15484
|
+
if (!params.anchor) {
|
|
15485
|
+
throw new Error("sender_auth: a per-intent anchor is required to derive a deterministic request_id (a random one would silently break idempotency and let a retry double-charge)");
|
|
15486
|
+
}
|
|
15487
|
+
if (!params.account) {
|
|
15488
|
+
throw new Error("sender_auth: account is required to derive a deterministic request_id");
|
|
15489
|
+
}
|
|
15490
|
+
if (!/^[A-Za-z0-9_-]*$/.test(params.prefix)) {
|
|
15491
|
+
throw new Error(`sender_auth: request_id prefix must contain only letters, digits, '_' or '-' (got ${JSON.stringify(params.prefix)})`);
|
|
15492
|
+
}
|
|
15493
|
+
const digest = (0, ethers_1.keccak256)((0, ethers_1.toUtf8Bytes)(`${exports2.REQUEST_ID_DOMAIN}${params.anchor}:${canonicalDepositor2(params.account)}`));
|
|
15494
|
+
return `${params.prefix}${digest.slice(2, 26)}`;
|
|
15495
|
+
}
|
|
15476
15496
|
function sameAddress(a, b) {
|
|
15477
15497
|
if (a.startsWith("0x") && b.startsWith("0x")) {
|
|
15478
15498
|
return a.toLowerCase() === b.toLowerCase();
|
|
@@ -16044,7 +16064,7 @@ var require_dist2 = __commonJS({
|
|
|
16044
16064
|
exports2.evmAdapter = {
|
|
16045
16065
|
async buildAuthMessage({ sourceAsset, maxSourceAmount, sourceDefaults, deadline, nonce }) {
|
|
16046
16066
|
if (nonce === void 0) {
|
|
16047
|
-
throw new Error("sender_auth: buildAuthMessage requires an explicit nonce \u2014 derive it deterministically from a stable request id (e.g.
|
|
16067
|
+
throw new Error("sender_auth: buildAuthMessage requires an explicit nonce \u2014 derive it deterministically from a stable request id (e.g. an order id) so retries reproduce the same permit; pass generatePermitNonce() only for genuinely one-shot builds");
|
|
16048
16068
|
}
|
|
16049
16069
|
if (deadline === void 0) {
|
|
16050
16070
|
throw new Error("sender_auth: buildAuthMessage requires an explicit permit deadline (absolute Unix seconds) \u2014 the low-level builder does not default it; derive it from the payment's fulfillment/settlement deadline in the calling layer (pgc/mppx)");
|
|
@@ -16072,6 +16092,10 @@ var require_dist2 = __commonJS({
|
|
|
16072
16092
|
throw new Error("EVM adapter sign(): signed_messages[i].message_prehash is required");
|
|
16073
16093
|
}
|
|
16074
16094
|
const prehash = JSON.parse(signedMessage.message_prehash);
|
|
16095
|
+
const prehashDigest = (0, evm_escrow_encoding_1.hashPermitWitnessTransferFrom)(prehash);
|
|
16096
|
+
if (prehashDigest.toLowerCase() !== signedMessage.message.toLowerCase()) {
|
|
16097
|
+
throw new Error(`EVM adapter sign(): message_prehash implies digest ${prehashDigest} but message is ${signedMessage.message}`);
|
|
16098
|
+
}
|
|
16075
16099
|
const wallet = new ethers_1.Wallet(privateKey);
|
|
16076
16100
|
return wallet.signTypedData(prehash.domain, prehash.types, prehash.message);
|
|
16077
16101
|
},
|
|
@@ -16149,14 +16173,14 @@ var require_dist2 = __commonJS({
|
|
|
16149
16173
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
16150
16174
|
exports2.tronAdapter = void 0;
|
|
16151
16175
|
var ethers_1 = __require("ethers");
|
|
16152
|
-
var tvm_escrow_encoding_1 =
|
|
16176
|
+
var tvm_escrow_encoding_1 = require_dist4();
|
|
16153
16177
|
var utils_js_1 = require_utils();
|
|
16154
16178
|
var errors_js_1 = require_errors();
|
|
16155
16179
|
var chain_id_js_1 = require_chain_id2();
|
|
16156
16180
|
exports2.tronAdapter = {
|
|
16157
16181
|
async buildAuthMessage({ sourceAsset, maxSourceAmount, sourceDefaults, deadline, nonce }) {
|
|
16158
16182
|
if (nonce === void 0) {
|
|
16159
|
-
throw new Error("sender_auth: buildAuthMessage requires an explicit nonce \u2014 derive it deterministically from a stable request id (e.g.
|
|
16183
|
+
throw new Error("sender_auth: buildAuthMessage requires an explicit nonce \u2014 derive it deterministically from a stable request id (e.g. an order id) so retries reproduce the same permit; pass generatePermitNonce() only for genuinely one-shot builds");
|
|
16160
16184
|
}
|
|
16161
16185
|
if (deadline === void 0) {
|
|
16162
16186
|
throw new Error("sender_auth: buildAuthMessage requires an explicit permit deadline (absolute Unix seconds) \u2014 the low-level builder does not default it; derive it from the payment's fulfillment/settlement deadline in the calling layer (pgc/mppx)");
|
|
@@ -16179,9 +16203,19 @@ var require_dist2 = __commonJS({
|
|
|
16179
16203
|
const messageHash = (0, tvm_escrow_encoding_1.hashTvmPermitWitnessTransferFrom)(messagePrehash);
|
|
16180
16204
|
return { messageScheme: "EVM_PERMIT2", messageHash, messagePrehash: JSON.stringify(messagePrehash) };
|
|
16181
16205
|
},
|
|
16206
|
+
// Signs the TIP-712 typed data, not the bare digest, so a signer can inspect the fields it is
|
|
16207
|
+
// authorizing (Turnkey policies read `eth.eip_712.message[...]`).
|
|
16182
16208
|
async sign(signedMessage, privateKey) {
|
|
16209
|
+
if (!signedMessage.message_prehash) {
|
|
16210
|
+
throw new Error("Tron adapter sign(): signed_messages[i].message_prehash is required");
|
|
16211
|
+
}
|
|
16212
|
+
const prehash = JSON.parse(signedMessage.message_prehash);
|
|
16213
|
+
const prehashDigest = (0, tvm_escrow_encoding_1.hashTvmPermitWitnessTransferFrom)(prehash);
|
|
16214
|
+
if (prehashDigest.toLowerCase() !== signedMessage.message.toLowerCase()) {
|
|
16215
|
+
throw new Error(`Tron adapter sign(): message_prehash implies digest ${prehashDigest} but message is ${signedMessage.message}`);
|
|
16216
|
+
}
|
|
16183
16217
|
const wallet = new ethers_1.Wallet(privateKey.startsWith("0x") ? privateKey : "0x" + privateKey);
|
|
16184
|
-
return wallet.
|
|
16218
|
+
return wallet.signTypedData(prehash.domain, prehash.types, prehash.message);
|
|
16185
16219
|
},
|
|
16186
16220
|
recoverSigner(signed, source) {
|
|
16187
16221
|
let recovered;
|
|
@@ -17497,7 +17531,7 @@ var require_dist2 = __commonJS({
|
|
|
17497
17531
|
}
|
|
17498
17532
|
}
|
|
17499
17533
|
});
|
|
17500
|
-
var
|
|
17534
|
+
var require_dist42 = __commonJS2({
|
|
17501
17535
|
"../schemas/declarations/PaymentRequest/v1/bindings/typescript/sender-auth/dist/index.js"(exports2) {
|
|
17502
17536
|
"use strict";
|
|
17503
17537
|
var __createBinding = exports2 && exports2.__createBinding || (Object.create ? (function(o, m, k, k2) {
|
|
@@ -17782,6 +17816,7 @@ var require_dist2 = __commonJS({
|
|
|
17782
17816
|
retryCounter;
|
|
17783
17817
|
backoffHistogram;
|
|
17784
17818
|
activityPendingCounter;
|
|
17819
|
+
signDurationHistogram;
|
|
17785
17820
|
// The private API scalar is held only long enough to construct the stamper. After
|
|
17786
17821
|
// `getStamper()` runs, this is nulled out so the hex string doesn't survive on the heap
|
|
17787
17822
|
// for the client's lifetime. Web Crypto holds the imported key as an opaque CryptoKey.
|
|
@@ -17810,6 +17845,10 @@ var require_dist2 = __commonJS({
|
|
|
17810
17845
|
this.activityPendingCounter = meter.createCounter("turnkey.activity_pending_total", {
|
|
17811
17846
|
description: "Activities that entered async polling (did not complete synchronously in the submit response), labeled by activity type"
|
|
17812
17847
|
});
|
|
17848
|
+
this.signDurationHistogram = meter.createHistogram("turnkey.sign_duration_ms", {
|
|
17849
|
+
description: "Full Turnkey activity round-trip latency (concurrency-semaphore wait + submit + poll), labeled by activity type and outcome (success|error)",
|
|
17850
|
+
unit: "ms"
|
|
17851
|
+
});
|
|
17813
17852
|
}
|
|
17814
17853
|
emitRetry(reason, path) {
|
|
17815
17854
|
try {
|
|
@@ -17829,6 +17868,12 @@ var require_dist2 = __commonJS({
|
|
|
17829
17868
|
} catch {
|
|
17830
17869
|
}
|
|
17831
17870
|
}
|
|
17871
|
+
emitSignDuration(durationMs, activityType, outcome) {
|
|
17872
|
+
try {
|
|
17873
|
+
this.signDurationHistogram.record(durationMs, { activity_type: activityType, outcome });
|
|
17874
|
+
} catch {
|
|
17875
|
+
}
|
|
17876
|
+
}
|
|
17832
17877
|
// ── public surface ─────────────────────────────────────────────────────────
|
|
17833
17878
|
/** Boot-time reachability + auth probe. Throws TURNKEY_AUTH on bad credentials. */
|
|
17834
17879
|
async whoami() {
|
|
@@ -17878,39 +17923,46 @@ var require_dist2 = __commonJS({
|
|
|
17878
17923
|
}
|
|
17879
17924
|
// ── activity submission ────────────────────────────────────────────────────
|
|
17880
17925
|
async submitActivity(activityType, endpoint, parameters) {
|
|
17881
|
-
const
|
|
17882
|
-
|
|
17883
|
-
|
|
17884
|
-
|
|
17885
|
-
|
|
17886
|
-
|
|
17887
|
-
|
|
17888
|
-
|
|
17889
|
-
|
|
17890
|
-
|
|
17891
|
-
|
|
17892
|
-
|
|
17893
|
-
|
|
17894
|
-
|
|
17895
|
-
|
|
17896
|
-
|
|
17897
|
-
|
|
17898
|
-
throw (0, km_core_1.signerRetryable)(km_core_1.SignerErrorCode.TURNKEY_SIGNER_UNAVAILABLE, `Turnkey ${ctx} activityId=${activity.id} stayed PENDING past ${POLL_TIMEOUT_MS}ms`);
|
|
17926
|
+
const start = Date.now();
|
|
17927
|
+
let outcome = "error";
|
|
17928
|
+
try {
|
|
17929
|
+
const body = {
|
|
17930
|
+
type: activityType,
|
|
17931
|
+
timestampMs: String(Date.now()),
|
|
17932
|
+
organizationId: this.opts.organizationId,
|
|
17933
|
+
parameters
|
|
17934
|
+
};
|
|
17935
|
+
const signWith = typeof parameters.signWith === "string" ? parameters.signWith : void 0;
|
|
17936
|
+
const ctx = `activity=${activityType}${signWith ? ` signWith=${signWith}` : ""}`;
|
|
17937
|
+
const resp = await this.queryPost(`/public/v1/submit/${endpoint}`, body);
|
|
17938
|
+
let activity = resp.activity;
|
|
17939
|
+
const deadline = Date.now() + POLL_TIMEOUT_MS;
|
|
17940
|
+
let pollAttempt = 0;
|
|
17941
|
+
if (activity?.status === "ACTIVITY_STATUS_PENDING") {
|
|
17942
|
+
this.emitActivityPending(activityType);
|
|
17899
17943
|
}
|
|
17900
|
-
|
|
17901
|
-
|
|
17902
|
-
|
|
17903
|
-
|
|
17904
|
-
|
|
17905
|
-
|
|
17906
|
-
|
|
17907
|
-
|
|
17908
|
-
|
|
17909
|
-
|
|
17910
|
-
|
|
17911
|
-
|
|
17944
|
+
while (activity?.status === "ACTIVITY_STATUS_PENDING") {
|
|
17945
|
+
if (Date.now() > deadline) {
|
|
17946
|
+
throw (0, km_core_1.signerRetryable)(km_core_1.SignerErrorCode.TURNKEY_SIGNER_UNAVAILABLE, `Turnkey ${ctx} activityId=${activity.id} stayed PENDING past ${POLL_TIMEOUT_MS}ms`);
|
|
17947
|
+
}
|
|
17948
|
+
const sleepIdx = Math.min(pollAttempt, POLL_BACKOFF_MS.length - 1);
|
|
17949
|
+
await (0, promises_1.setTimeout)(POLL_BACKOFF_MS[sleepIdx]);
|
|
17950
|
+
pollAttempt++;
|
|
17951
|
+
const polled = await this.queryPost("/public/v1/query/get_activity", { organizationId: this.opts.organizationId, activityId: activity.id });
|
|
17952
|
+
activity = polled.activity;
|
|
17953
|
+
}
|
|
17954
|
+
if (activity?.status !== "ACTIVITY_STATUS_COMPLETED") {
|
|
17955
|
+
const failure = activity?.failure ?? {};
|
|
17956
|
+
throw (0, km_core_1.signerTerminal)(km_core_1.SignerErrorCode.TURNKEY_ACTIVITY_FAILED, `Turnkey ${ctx} activityId=${activity?.id ?? "?"} status=${activity?.status ?? "unknown"}; ${JSON.stringify(failure)}`);
|
|
17957
|
+
}
|
|
17958
|
+
if (activity.result == null) {
|
|
17959
|
+
throw (0, km_core_1.signerTerminal)(km_core_1.SignerErrorCode.TURNKEY_BAD_RESPONSE, `Turnkey ${ctx} activityId=${activity.id} COMPLETED but result was missing`);
|
|
17960
|
+
}
|
|
17961
|
+
outcome = "success";
|
|
17962
|
+
return activity.result;
|
|
17963
|
+
} finally {
|
|
17964
|
+
this.emitSignDuration(Date.now() - start, activityType, outcome);
|
|
17912
17965
|
}
|
|
17913
|
-
return activity.result;
|
|
17914
17966
|
}
|
|
17915
17967
|
// ── HTTP layer ────────────────────────────────────────────────────────────
|
|
17916
17968
|
/**
|
|
@@ -18178,17 +18230,33 @@ var require_dist2 = __commonJS({
|
|
|
18178
18230
|
"use strict";
|
|
18179
18231
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
18180
18232
|
exports2.signSecp256k1PreimageAndVerify = signSecp256k1PreimageAndVerify;
|
|
18233
|
+
exports2.signSecp256k1TypedDataAndVerify = signSecp256k1TypedDataAndVerify;
|
|
18181
18234
|
exports2.bytesFromHexOrBytes = bytesFromHexOrBytes;
|
|
18182
18235
|
var ethers_1 = __require("ethers");
|
|
18183
18236
|
var km_core_1 = require_dist5();
|
|
18237
|
+
var EIP712_HASH_FUNCTION = "HASH_FUNCTION_NOT_APPLICABLE";
|
|
18184
18238
|
async function signSecp256k1PreimageAndVerify(client, signWith, preimage, expectedEvmAddrLower) {
|
|
18185
18239
|
const preimageHex = (0, ethers_1.hexlify)(preimage).slice(2);
|
|
18186
|
-
const
|
|
18240
|
+
const parts = await client.signRawPayload({
|
|
18187
18241
|
signWith,
|
|
18188
18242
|
payload: preimageHex,
|
|
18189
18243
|
encoding: "PAYLOAD_ENCODING_HEXADECIMAL",
|
|
18190
18244
|
hashFunction: "HASH_FUNCTION_KECCAK256"
|
|
18191
18245
|
});
|
|
18246
|
+
return recoverAndVerify(parts, (0, ethers_1.keccak256)(preimage), expectedEvmAddrLower);
|
|
18247
|
+
}
|
|
18248
|
+
async function signSecp256k1TypedDataAndVerify(client, signWith, domain, types, message, expectedEvmAddrLower) {
|
|
18249
|
+
const payload = ethers_1.TypedDataEncoder.getPayload(domain, types, message);
|
|
18250
|
+
const parts = await client.signRawPayload({
|
|
18251
|
+
signWith,
|
|
18252
|
+
payload: JSON.stringify(payload),
|
|
18253
|
+
encoding: "PAYLOAD_ENCODING_EIP712",
|
|
18254
|
+
hashFunction: EIP712_HASH_FUNCTION
|
|
18255
|
+
});
|
|
18256
|
+
const digestHex = ethers_1.TypedDataEncoder.hash(domain, types, message);
|
|
18257
|
+
return recoverAndVerify(parts, digestHex, expectedEvmAddrLower);
|
|
18258
|
+
}
|
|
18259
|
+
function recoverAndVerify({ r, s, v }, digestHex, expectedEvmAddrLower) {
|
|
18192
18260
|
let sig;
|
|
18193
18261
|
try {
|
|
18194
18262
|
sig = ethers_1.Signature.from({
|
|
@@ -18199,7 +18267,6 @@ var require_dist2 = __commonJS({
|
|
|
18199
18267
|
} catch (err) {
|
|
18200
18268
|
throw (0, km_core_1.signerTerminal)(km_core_1.SignerErrorCode.TURNKEY_BAD_RESPONSE, `Turnkey returned malformed secp256k1 signature parts r=${r} s=${s} v=${v}`, err instanceof Error ? err : void 0);
|
|
18201
18269
|
}
|
|
18202
|
-
const digestHex = (0, ethers_1.keccak256)(preimage);
|
|
18203
18270
|
const recovered = (0, ethers_1.recoverAddress)(digestHex, sig).toLowerCase();
|
|
18204
18271
|
if (recovered !== expectedEvmAddrLower) {
|
|
18205
18272
|
throw (0, km_core_1.signerTerminal)(km_core_1.SignerErrorCode.TURNKEY_BAD_RESPONSE, `secp256k1 sign-then-recover mismatch: recovered ${recovered}, expected ${expectedEvmAddrLower}`);
|
|
@@ -18261,8 +18328,7 @@ ${msgBytes.length}`);
|
|
|
18261
18328
|
}
|
|
18262
18329
|
async signTypedData(domain, types, message) {
|
|
18263
18330
|
const { signWith, lower } = this.requireAddresses();
|
|
18264
|
-
|
|
18265
|
-
return (0, secp256k1_helpers_1.signSecp256k1PreimageAndVerify)(this.client, signWith, preimage, lower);
|
|
18331
|
+
return (0, secp256k1_helpers_1.signSecp256k1TypedDataAndVerify)(this.client, signWith, domain, types, message, lower);
|
|
18266
18332
|
}
|
|
18267
18333
|
async signTransaction(tx) {
|
|
18268
18334
|
const { signWith, lower } = this.requireAddresses();
|
|
@@ -18377,6 +18443,7 @@ ${msgBytes.length}`);
|
|
|
18377
18443
|
};
|
|
18378
18444
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
18379
18445
|
exports2.TurnkeySolanaSigner = void 0;
|
|
18446
|
+
exports2.encodePayload = encodePayload;
|
|
18380
18447
|
var web3_js_1 = __require("@solana/web3.js");
|
|
18381
18448
|
var bs58_1 = __importDefault(__require("bs58"));
|
|
18382
18449
|
var km_core_1 = require_dist5();
|
|
@@ -18410,8 +18477,7 @@ ${msgBytes.length}`);
|
|
|
18410
18477
|
}
|
|
18411
18478
|
const { r, s } = await this.client.signRawPayload({
|
|
18412
18479
|
signWith: this.address,
|
|
18413
|
-
|
|
18414
|
-
encoding: "PAYLOAD_ENCODING_HEXADECIMAL",
|
|
18480
|
+
...encodePayload(bytes),
|
|
18415
18481
|
hashFunction: "HASH_FUNCTION_NOT_APPLICABLE"
|
|
18416
18482
|
});
|
|
18417
18483
|
const sig = Buffer.concat([Buffer.from(stripHex(r), "hex"), Buffer.from(stripHex(s), "hex")]);
|
|
@@ -18452,6 +18518,15 @@ ${msgBytes.length}`);
|
|
|
18452
18518
|
}
|
|
18453
18519
|
};
|
|
18454
18520
|
exports2.TurnkeySolanaSigner = TurnkeySolanaSigner2;
|
|
18521
|
+
function encodePayload(bytes) {
|
|
18522
|
+
const buf = Buffer.from(bytes);
|
|
18523
|
+
const text = buf.toString("utf8");
|
|
18524
|
+
const textual = buf.every((b) => b >= 32 && b <= 126 || b === 9 || b === 10 || b === 13);
|
|
18525
|
+
if (textual && Buffer.from(text, "utf8").equals(buf)) {
|
|
18526
|
+
return { payload: text, encoding: "PAYLOAD_ENCODING_TEXT_UTF8" };
|
|
18527
|
+
}
|
|
18528
|
+
return { payload: buf.toString("hex"), encoding: "PAYLOAD_ENCODING_HEXADECIMAL" };
|
|
18529
|
+
}
|
|
18455
18530
|
function stripHex(s) {
|
|
18456
18531
|
return s.startsWith("0x") ? s.slice(2) : s;
|
|
18457
18532
|
}
|
|
@@ -18517,8 +18592,7 @@ ${messageBytes.length}`);
|
|
|
18517
18592
|
}
|
|
18518
18593
|
async signTypedData(domain, types, message) {
|
|
18519
18594
|
const { address, evmAddr } = this.requireReady();
|
|
18520
|
-
|
|
18521
|
-
return (0, secp256k1_helpers_1.signSecp256k1PreimageAndVerify)(this.client, address, preimage, evmAddr);
|
|
18595
|
+
return (0, secp256k1_helpers_1.signSecp256k1TypedDataAndVerify)(this.client, address, domain, types, message, evmAddr);
|
|
18522
18596
|
}
|
|
18523
18597
|
async signTransaction(tx) {
|
|
18524
18598
|
const { address, evmAddr } = this.requireReady();
|
|
@@ -18889,7 +18963,7 @@ ${messageBytes.length}`);
|
|
|
18889
18963
|
policyName: "allowSignRawPayload",
|
|
18890
18964
|
effect: "EFFECT_ALLOW",
|
|
18891
18965
|
condition: `activity.type in ['ACTIVITY_TYPE_SIGN_RAW_PAYLOAD_V2', 'ACTIVITY_TYPE_SIGN_RAW_PAYLOADS'] && activity.params.hash_function in ['HASH_FUNCTION_KECCAK256', 'HASH_FUNCTION_NOT_APPLICABLE']`,
|
|
18892
|
-
notes: "Allows signRawPayload with the hash functions the
|
|
18966
|
+
notes: "Allows signRawPayload with the hash functions the runtime uses: KECCAK256 (EIP-191/TIP-191/W3C proofs) and NOT_APPLICABLE (Solana ed25519 + EIP-712 typed data)."
|
|
18893
18967
|
};
|
|
18894
18968
|
}
|
|
18895
18969
|
function buildDenyApproveToNonAllowedSpenderEvm(args) {
|
|
@@ -19526,7 +19600,7 @@ ${detail}`);
|
|
|
19526
19600
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports3, p)) __createBinding(exports3, m, p);
|
|
19527
19601
|
};
|
|
19528
19602
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
19529
|
-
exports2.bytesFromHexOrBytes = exports2.signSecp256k1PreimageAndVerify = exports2.extractTronSignatureFromTransactionProtobuf = exports2.TurnkeyTronSigner = exports2.TurnkeySolanaSigner = exports2.TurnkeyEvmSigner = exports2.noopMeter = exports2.noopLogger = exports2.TURNKEY_RETRY_BACKOFF_MS = exports2.resolveTurnkeyAccountAddress = exports2.p1363ToDer = exports2.createTurnkeyStamper = exports2.createIsolatedTurnkeyClient = exports2.getOrCreateTurnkeyClient = exports2.TurnkeyClient = void 0;
|
|
19603
|
+
exports2.bytesFromHexOrBytes = exports2.signSecp256k1PreimageAndVerify = exports2.extractTronSignatureFromTransactionProtobuf = exports2.TurnkeyTronSigner = exports2.encodePayload = exports2.TurnkeySolanaSigner = exports2.TurnkeyEvmSigner = exports2.noopMeter = exports2.noopLogger = exports2.TURNKEY_RETRY_BACKOFF_MS = exports2.resolveTurnkeyAccountAddress = exports2.p1363ToDer = exports2.createTurnkeyStamper = exports2.createIsolatedTurnkeyClient = exports2.getOrCreateTurnkeyClient = exports2.TurnkeyClient = void 0;
|
|
19530
19604
|
var client_1 = require_client();
|
|
19531
19605
|
Object.defineProperty(exports2, "TurnkeyClient", { enumerable: true, get: function() {
|
|
19532
19606
|
return client_1.TurnkeyClient;
|
|
@@ -19569,6 +19643,9 @@ ${detail}`);
|
|
|
19569
19643
|
Object.defineProperty(exports2, "TurnkeySolanaSigner", { enumerable: true, get: function() {
|
|
19570
19644
|
return solana_1.TurnkeySolanaSigner;
|
|
19571
19645
|
} });
|
|
19646
|
+
Object.defineProperty(exports2, "encodePayload", { enumerable: true, get: function() {
|
|
19647
|
+
return solana_1.encodePayload;
|
|
19648
|
+
} });
|
|
19572
19649
|
var tron_1 = require_tron2();
|
|
19573
19650
|
Object.defineProperty(exports2, "TurnkeyTronSigner", { enumerable: true, get: function() {
|
|
19574
19651
|
return tron_1.TurnkeyTronSigner;
|
|
@@ -19628,13 +19705,13 @@ ${detail}`);
|
|
|
19628
19705
|
};
|
|
19629
19706
|
switch (chainPrefix) {
|
|
19630
19707
|
case "eip155": {
|
|
19631
|
-
const { domain, types, message: typedMessage } = parsePrehash(messagePrehash, "EVM");
|
|
19708
|
+
const { domain, types, message: typedMessage } = parsePrehash(messagePrehash, "EVM", message);
|
|
19632
19709
|
const signer = new import_turnkey_signer.TurnkeyEvmSigner(client, deps);
|
|
19633
19710
|
await signer.initialize();
|
|
19634
19711
|
return { signature: await signer.signTypedData(domain, types, typedMessage) };
|
|
19635
19712
|
}
|
|
19636
19713
|
case "tron": {
|
|
19637
|
-
const { domain, types, message: typedMessage } = parsePrehash(messagePrehash, "Tron");
|
|
19714
|
+
const { domain, types, message: typedMessage } = parsePrehash(messagePrehash, "Tron", message);
|
|
19638
19715
|
const signer = new import_turnkey_signer.TurnkeyTronSigner(client, deps);
|
|
19639
19716
|
await signer.initialize();
|
|
19640
19717
|
return { signature: await signer.signTypedData(domain, types, typedMessage) };
|
|
@@ -19662,7 +19739,7 @@ ${detail}`);
|
|
|
19662
19739
|
}
|
|
19663
19740
|
return Uint8Array.from(Buffer.from(hex, "hex"));
|
|
19664
19741
|
}
|
|
19665
|
-
function parsePrehash(messagePrehash, label) {
|
|
19742
|
+
function parsePrehash(messagePrehash, label, advertisedDigest) {
|
|
19666
19743
|
if (!messagePrehash) {
|
|
19667
19744
|
throw new Error(`Turnkey ${label} signing requires signed_messages[0].message_prehash`);
|
|
19668
19745
|
}
|
|
@@ -19676,15 +19753,24 @@ ${detail}`);
|
|
|
19676
19753
|
if (!isObject(parsed) || !isObject(parsed.domain) || !isObject(parsed.types) || !isObject(parsed.message)) {
|
|
19677
19754
|
throw new Error(`Turnkey ${label} signing: message_prehash must be a JSON object with domain, types and message`);
|
|
19678
19755
|
}
|
|
19679
|
-
|
|
19756
|
+
const { EIP712Domain: _derived, ...structTypes } = parsed.types;
|
|
19757
|
+
const prehashDigest = import_ethers5.TypedDataEncoder.hash(parsed.domain, structTypes, parsed.message);
|
|
19758
|
+
if (prehashDigest.toLowerCase() !== advertisedDigest.toLowerCase()) {
|
|
19759
|
+
throw new Error(
|
|
19760
|
+
`Turnkey ${label} signing: message_prehash implies digest ${prehashDigest} but message is ${advertisedDigest}`
|
|
19761
|
+
);
|
|
19762
|
+
}
|
|
19763
|
+
return { domain: parsed.domain, types: structTypes, message: parsed.message };
|
|
19680
19764
|
}
|
|
19681
19765
|
var import_turnkey_signer;
|
|
19766
|
+
var import_ethers5;
|
|
19682
19767
|
var TURNKEY_API_URL;
|
|
19683
19768
|
var DEFAULTS;
|
|
19684
19769
|
var init_turnkey_impl = __esm2({
|
|
19685
19770
|
"src/signers/turnkey-impl.ts"() {
|
|
19686
19771
|
"use strict";
|
|
19687
19772
|
import_turnkey_signer = __toESM2(require_dist6());
|
|
19773
|
+
import_ethers5 = __require("ethers");
|
|
19688
19774
|
TURNKEY_API_URL = "https://api.turnkey.com";
|
|
19689
19775
|
DEFAULTS = {
|
|
19690
19776
|
concurrencyLimit: 10,
|
|
@@ -20189,8 +20275,26 @@ ${detail}`);
|
|
|
20189
20275
|
* 2. Find optimal settlement routes across chains/assets
|
|
20190
20276
|
* 3. Secure funds in escrow
|
|
20191
20277
|
* 4. Coordinate with settlement agents for execution
|
|
20192
|
-
* 5. Return a real-time result if
|
|
20193
|
-
* otherwise return a payment ID
|
|
20278
|
+
* 5. Return a real-time result if settlement completes inside the synchronous window,
|
|
20279
|
+
* otherwise return a payment ID and status for polling
|
|
20280
|
+
*
|
|
20281
|
+
* **Idempotency.** `request_id` is the idempotency key, scoped to the source account
|
|
20282
|
+
* and originator. Submitting the same `request_id` again returns the ORIGINAL payment
|
|
20283
|
+
* instead of charging a second time, so a client whose request timed out or failed
|
|
20284
|
+
* in transit can safely re-submit.
|
|
20285
|
+
*
|
|
20286
|
+
* Because a re-submission must be admissible on its own, some fields legitimately
|
|
20287
|
+
* differ between attempts and are excluded from the comparison: `quote_deadline` and
|
|
20288
|
+
* `fulfillment_deadline` (both must be in the future, so a later attempt has to move
|
|
20289
|
+
* them), and the `sender_auth` signature they are signed into.
|
|
20290
|
+
*
|
|
20291
|
+
* What must NOT differ is the payment's economics — source account and asset,
|
|
20292
|
+
* destination accounts and assets, `fulfillment_amount`, and `max_source_amount` (the
|
|
20293
|
+
* payer's own risk cap; lowering it on a retry describes a different payment, not the
|
|
20294
|
+
* same one with less headroom). Re-using one `request_id` for a genuinely different
|
|
20295
|
+
* payment is a client bug that would otherwise be silently collapsed onto the first
|
|
20296
|
+
* payment, so it is rejected with `409` and `IDEMPOTENCY_TERMS_MISMATCH`. Use a
|
|
20297
|
+
* distinct `request_id` per payment.
|
|
20194
20298
|
*
|
|
20195
20299
|
* @param data The data for the request.
|
|
20196
20300
|
* @param data.requestBody
|
|
@@ -20207,6 +20311,11 @@ ${detail}`);
|
|
|
20207
20311
|
400: "Invalid request",
|
|
20208
20312
|
401: "Signature or sender authorization could not be verified",
|
|
20209
20313
|
403: "Payment declined during counterparty authorization",
|
|
20314
|
+
409: `The \`request_id\` has already been used for a payment with different economics
|
|
20315
|
+
(\`IDEMPOTENCY_TERMS_MISMATCH\`). Re-submitting one \`request_id\` is how a retry is
|
|
20316
|
+
made safe, so it must identify one payment; use a distinct \`request_id\` per
|
|
20317
|
+
payment.
|
|
20318
|
+
`,
|
|
20210
20319
|
413: "Payment request too large to process",
|
|
20211
20320
|
500: "Internal server error",
|
|
20212
20321
|
503: "A dependency is temporarily unavailable"
|
|
@@ -20539,7 +20648,7 @@ ${detail}`);
|
|
|
20539
20648
|
}
|
|
20540
20649
|
};
|
|
20541
20650
|
var import_ethers22 = __require("ethers");
|
|
20542
|
-
var import_tvm_escrow_encoding = __toESM2(
|
|
20651
|
+
var import_tvm_escrow_encoding = __toESM2(require_dist4());
|
|
20543
20652
|
var tronAdapter = {
|
|
20544
20653
|
turnkeyAddressFormat: "ADDRESS_FORMAT_TRON",
|
|
20545
20654
|
resolveContractOverrides(sourceDefaults) {
|
|
@@ -20685,7 +20794,7 @@ ${detail}`);
|
|
|
20685
20794
|
}
|
|
20686
20795
|
return BigInt(Math.floor(Date.now() / 1e3)) - SOLANA_ISSUED_AT_FALLBACK_SKEW_SECS;
|
|
20687
20796
|
}
|
|
20688
|
-
var import_payment_request_sender_auth2 = __toESM2(
|
|
20797
|
+
var import_payment_request_sender_auth2 = __toESM2(require_dist42());
|
|
20689
20798
|
var $AuthorizationResult = {
|
|
20690
20799
|
type: "object",
|
|
20691
20800
|
description: `The result of a counterparty authorization request. Contains either
|
|
@@ -21177,11 +21286,18 @@ Required when regulatory compliance or KYC verification is needed for the paymen
|
|
|
21177
21286
|
};
|
|
21178
21287
|
var $PaymentResponse = {
|
|
21179
21288
|
type: "object",
|
|
21180
|
-
description: `Response from submitting a payment request. If
|
|
21181
|
-
the response
|
|
21182
|
-
Otherwise
|
|
21183
|
-
/v1/payments/{paymentId}/status
|
|
21289
|
+
description: `Response from submitting a payment request. If settlement completes inside the
|
|
21290
|
+
gateway's synchronous window, the response includes a fulfillment_confirmation with
|
|
21291
|
+
full settlement details. Otherwise you receive a payment_id plus the payment's
|
|
21292
|
+
current \`status\`, and can poll /v1/payments/{paymentId}/status for updates.
|
|
21293
|
+
|
|
21294
|
+
Read \`status\` before deciding what to do next: a \`pending\` payment is in flight and
|
|
21295
|
+
must NOT be re-submitted under a new request_id (that would be a second payment),
|
|
21296
|
+
whereas a \`failed\` or \`cancelled\` one is terminal \u2014 re-submitting it under the SAME
|
|
21297
|
+
request_id resolves to the same terminal payment, so a genuine re-attempt needs a
|
|
21298
|
+
new request_id.
|
|
21184
21299
|
`,
|
|
21300
|
+
required: ["payment_id", "status", "idempotent_replay"],
|
|
21185
21301
|
properties: {
|
|
21186
21302
|
payment_id: {
|
|
21187
21303
|
type: "string",
|
|
@@ -21189,8 +21305,60 @@ Otherwise, you'll receive a payment_id that you can use to poll the
|
|
|
21189
21305
|
`,
|
|
21190
21306
|
example: "550e8400-e29b-41d4-a716-446655440000"
|
|
21191
21307
|
},
|
|
21308
|
+
status: {
|
|
21309
|
+
type: "string",
|
|
21310
|
+
enum: ["pending", "completed", "failed", "cancelled"],
|
|
21311
|
+
description: `Current status of the payment, with the same meaning as on
|
|
21312
|
+
/v1/payments/{paymentId}/status:
|
|
21313
|
+
- \`pending\`: accepted and being processed
|
|
21314
|
+
- \`completed\`: successfully delivered
|
|
21315
|
+
- \`failed\`: failed (funds returned if escrowed)
|
|
21316
|
+
- \`cancelled\`: cancelled before completion
|
|
21317
|
+
|
|
21318
|
+
Present on every response. \`completed\` is always accompanied by
|
|
21319
|
+
fulfillment_confirmation; \`failed\` is accompanied by \`error\` where a reason has
|
|
21320
|
+
been recorded.
|
|
21321
|
+
`
|
|
21322
|
+
},
|
|
21323
|
+
idempotent_replay: {
|
|
21324
|
+
type: "boolean",
|
|
21325
|
+
description: `Whether this response describes a payment that already existed, rather than one
|
|
21326
|
+
created by this request. \`true\` means the request_id had been used before and you
|
|
21327
|
+
are being handed the ORIGINAL payment \u2014 no second payment was created and nothing
|
|
21328
|
+
additional was charged.
|
|
21329
|
+
|
|
21330
|
+
**Re-attempting a payment.** Re-submit the same request and you get the same payment
|
|
21331
|
+
back. You may re-send the original bytes unchanged: the deadlines will have expired by
|
|
21332
|
+
then \u2014 \`quote_deadline\` bounds the auction and is short, while this endpoint may hold a
|
|
21333
|
+
submission for up to 30 seconds \u2014 and an expired deadline on a re-submission is not an
|
|
21334
|
+
error, because the request is resolved onto the payment that already exists rather than
|
|
21335
|
+
used to create one.
|
|
21336
|
+
|
|
21337
|
+
Re-signing with fresh deadlines is equally fine and returns the same payment. What you
|
|
21338
|
+
must NOT change is the request_id, and what you must not change under it is the
|
|
21339
|
+
payment's economics \u2014 source, destination, fulfillment_amount, max_source_amount \u2014 which
|
|
21340
|
+
are rejected with 409 IDEMPOTENCY_TERMS_MISMATCH. Deadlines and the signature are
|
|
21341
|
+
exempt precisely so that a re-attempt is possible.
|
|
21342
|
+
|
|
21343
|
+
A genuinely new payment needs a NEW request_id. In particular a \`failed\` payment is
|
|
21344
|
+
terminal: re-submitting its request_id keeps returning that dead payment, so recovering
|
|
21345
|
+
means starting a new one under a new key.
|
|
21346
|
+
|
|
21347
|
+
Present on every response, \`false\` for a newly created payment. A response without
|
|
21348
|
+
the field is from a gateway predating it, not a newly created payment.
|
|
21349
|
+
|
|
21350
|
+
This is the field to read when reconciling a suspected double charge: two
|
|
21351
|
+
submissions where the second reports \`true\` are one payment, whereas two both
|
|
21352
|
+
reporting \`false\` are two. It says nothing about how far the payment has got \u2014
|
|
21353
|
+
read \`status\` for that.
|
|
21354
|
+
`,
|
|
21355
|
+
example: false
|
|
21356
|
+
},
|
|
21192
21357
|
fulfillment_confirmation: {
|
|
21193
21358
|
"$ref": "#/components/schemas/FulfillmentConfirmation"
|
|
21359
|
+
},
|
|
21360
|
+
error: {
|
|
21361
|
+
"$ref": "#/components/schemas/PaymentError"
|
|
21194
21362
|
}
|
|
21195
21363
|
}
|
|
21196
21364
|
};
|
|
@@ -22280,12 +22448,12 @@ payment-status endpoint.
|
|
|
22280
22448
|
function generateSolanaNonce() {
|
|
22281
22449
|
return (0, import_solana_escrow_encoding.generateNonce)();
|
|
22282
22450
|
}
|
|
22283
|
-
var
|
|
22451
|
+
var import_payment_request_sender_auth3 = __toESM2(require_dist42());
|
|
22284
22452
|
var RawSenderSigner = class {
|
|
22285
22453
|
constructor(network, privateKey) {
|
|
22286
22454
|
const adapter = getChainAdapter(network);
|
|
22287
22455
|
adapter.validatePrivateKey?.(privateKey);
|
|
22288
|
-
this.inner = (0,
|
|
22456
|
+
this.inner = (0, import_payment_request_sender_auth3.localKeySigner)(network, adapter.formatPrivateKey(privateKey));
|
|
22289
22457
|
}
|
|
22290
22458
|
sign(signedMessage) {
|
|
22291
22459
|
return this.inner.sign(signedMessage);
|
|
@@ -22679,8 +22847,9 @@ payment-status endpoint.
|
|
|
22679
22847
|
|
|
22680
22848
|
// src/client.ts
|
|
22681
22849
|
var import_evm_escrow_encoding = __toESM(require_dist(), 1);
|
|
22682
|
-
var
|
|
22683
|
-
|
|
22850
|
+
var import_payment_request_sender_auth = __toESM(require_dist2(), 1);
|
|
22851
|
+
var import_payment_gateway_client = __toESM(require_dist3(), 1);
|
|
22852
|
+
import { Contract, MaxUint256 } from "ethers";
|
|
22684
22853
|
import { Credential, Method } from "mppx";
|
|
22685
22854
|
function registerClient(config) {
|
|
22686
22855
|
const now = config.now ?? (() => Date.now());
|
|
@@ -22693,14 +22862,16 @@ function registerClient(config) {
|
|
|
22693
22862
|
const nowMs = now();
|
|
22694
22863
|
if (!(extra.quoteDeadlineSeconds > 0 && extra.quoteDeadlineSeconds < extra.fulfillmentDeadlineSeconds)) {
|
|
22695
22864
|
throw new Error(
|
|
22696
|
-
`atum-escrow: deadline
|
|
22865
|
+
`atum-escrow: the challenge's deadline budgets cannot produce a settleable payment. quoteDeadlineSeconds must be above zero and below fulfillmentDeadlineSeconds, because quote collection has to close before settlement is due. Got quoteDeadlineSeconds=${extra.quoteDeadlineSeconds}, fulfillmentDeadlineSeconds=${extra.fulfillmentDeadlineSeconds}. These come from the corridor the resource server offered, so this is a merchant-side configuration problem rather than anything a payer can correct.`
|
|
22697
22866
|
);
|
|
22698
22867
|
}
|
|
22699
|
-
const
|
|
22700
|
-
|
|
22701
|
-
|
|
22702
|
-
|
|
22703
|
-
|
|
22868
|
+
const intentId = intentIdOf(challenge);
|
|
22869
|
+
if (intentId === void 0) {
|
|
22870
|
+
throw new Error(
|
|
22871
|
+
`atum-escrow: the challenge carries no '${INTENT_ID_META_KEY}' metadata, so this payment cannot be made retry-safe and is refused. The merchant must stamp a stable per-purchase identifier into the challenge metadata (see buildChargeChallenge); without it a retry would be charged as a second payment.`
|
|
22872
|
+
);
|
|
22873
|
+
}
|
|
22874
|
+
const requestId = chargeRequestId(intentId, account);
|
|
22704
22875
|
const sourceDefaults = chainDefaultsFromExtra(extra, source.network);
|
|
22705
22876
|
const sourceAssetId = assetIdentifier(source.network, source.asset);
|
|
22706
22877
|
const isSolana = namespace === "solana";
|
|
@@ -22733,7 +22904,12 @@ function registerClient(config) {
|
|
|
22733
22904
|
solanaRpcUrl: "atum-escrow:offline",
|
|
22734
22905
|
solanaClockReader: solanaIssuedAt != null ? async () => BigInt(solanaIssuedAt) : config.solanaClockReader ?? (async () => BigInt(Math.floor(nowMs / 1e3)))
|
|
22735
22906
|
} : {
|
|
22736
|
-
nonce:
|
|
22907
|
+
// No explicit nonce: `preparePaymentRequest` derives it from
|
|
22908
|
+
// (request_id, depositor) via the shared sender_auth SDK — the same
|
|
22909
|
+
// Go-parity-locked derivation every consumer uses. Since request_id is itself
|
|
22910
|
+
// anchored on the intentId above, a rebuild reproduces the same single-use
|
|
22911
|
+
// permit. Overriding it here would fork a second nonce recipe for no gain.
|
|
22912
|
+
//
|
|
22737
22913
|
// Keep the deposit deadline at least as late as fulfillment. pgc converts this
|
|
22738
22914
|
// relative budget to an absolute permit deadline against the same clock; round
|
|
22739
22915
|
// the budget up and add a second so it never truncates below fulfillment_deadline.
|
|
@@ -22746,7 +22922,7 @@ function registerClient(config) {
|
|
|
22746
22922
|
return Credential.serialize({
|
|
22747
22923
|
challenge,
|
|
22748
22924
|
payload: { paymentRequest },
|
|
22749
|
-
source: `did:pkh:${source.network}:${
|
|
22925
|
+
source: `did:pkh:${source.network}:${(0, import_payment_request_sender_auth.canonicalDepositor)(account)}`
|
|
22750
22926
|
});
|
|
22751
22927
|
}
|
|
22752
22928
|
});
|
|
@@ -22758,14 +22934,8 @@ function buildSenderSigner(network, signer, account) {
|
|
|
22758
22934
|
if (isSenderSigner(signer)) {
|
|
22759
22935
|
return signer;
|
|
22760
22936
|
}
|
|
22761
|
-
if (signer.provider === "turnkey") {
|
|
22762
|
-
throw new Error(
|
|
22763
|
-
"atum-escrow: construct a Turnkey SenderSigner with the payment-gateway client and pass it as `signer`"
|
|
22764
|
-
);
|
|
22765
|
-
}
|
|
22766
22937
|
return (0, import_payment_gateway_client.createSenderSigner)(network, {
|
|
22767
|
-
|
|
22768
|
-
privateKey: signer.privateKey,
|
|
22938
|
+
...signer,
|
|
22769
22939
|
pinnedAddress: signer.pinnedAddress ?? account
|
|
22770
22940
|
});
|
|
22771
22941
|
}
|