@bankofai/x402-evm 1.0.0-beta.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/README.md +172 -0
- package/dist/cjs/auth-capture/client/index.d.ts +44 -0
- package/dist/cjs/auth-capture/client/index.js +298 -0
- package/dist/cjs/auth-capture/client/index.js.map +1 -0
- package/dist/cjs/batch-settlement/client/file-storage.d.ts +47 -0
- package/dist/cjs/batch-settlement/client/file-storage.js +116 -0
- package/dist/cjs/batch-settlement/client/file-storage.js.map +1 -0
- package/dist/cjs/batch-settlement/client/index.d.ts +111 -0
- package/dist/cjs/batch-settlement/client/index.js +1565 -0
- package/dist/cjs/batch-settlement/client/index.js.map +1 -0
- package/dist/cjs/batch-settlement/facilitator/index.d.ts +72 -0
- package/dist/cjs/batch-settlement/facilitator/index.js +2102 -0
- package/dist/cjs/batch-settlement/facilitator/index.js.map +1 -0
- package/dist/cjs/batch-settlement/server/file-storage.d.ts +53 -0
- package/dist/cjs/batch-settlement/server/file-storage.js +181 -0
- package/dist/cjs/batch-settlement/server/file-storage.js.map +1 -0
- package/dist/cjs/batch-settlement/server/index.d.ts +491 -0
- package/dist/cjs/batch-settlement/server/index.js +1978 -0
- package/dist/cjs/batch-settlement/server/index.js.map +1 -0
- package/dist/cjs/batch-settlement/server/redis-storage.d.ts +87 -0
- package/dist/cjs/batch-settlement/server/redis-storage.js +181 -0
- package/dist/cjs/batch-settlement/server/redis-storage.js.map +1 -0
- package/dist/cjs/client/agent-wallet.d.ts +69 -0
- package/dist/cjs/client/agent-wallet.js +84 -0
- package/dist/cjs/client/agent-wallet.js.map +1 -0
- package/dist/cjs/exact/client/index.d.ts +63 -0
- package/dist/cjs/exact/client/index.js +739 -0
- package/dist/cjs/exact/client/index.js.map +1 -0
- package/dist/cjs/exact/facilitator/index.d.ts +141 -0
- package/dist/cjs/exact/facilitator/index.js +1989 -0
- package/dist/cjs/exact/facilitator/index.js.map +1 -0
- package/dist/cjs/exact/server/index.d.ts +118 -0
- package/dist/cjs/exact/server/index.js +326 -0
- package/dist/cjs/exact/server/index.js.map +1 -0
- package/dist/cjs/exact/v1/client/index.d.ts +38 -0
- package/dist/cjs/exact/v1/client/index.js +193 -0
- package/dist/cjs/exact/v1/client/index.js.map +1 -0
- package/dist/cjs/exact/v1/facilitator/index.d.ts +84 -0
- package/dist/cjs/exact/v1/facilitator/index.js +739 -0
- package/dist/cjs/exact/v1/facilitator/index.js.map +1 -0
- package/dist/cjs/facilitator/agent-wallet.d.ts +109 -0
- package/dist/cjs/facilitator/agent-wallet.js +105 -0
- package/dist/cjs/facilitator/agent-wallet.js.map +1 -0
- package/dist/cjs/index.d.ts +338 -0
- package/dist/cjs/index.js +2860 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/permit2-DK5A8alk.d.ts +729 -0
- package/dist/cjs/permit2-DhJRUcgY.d.ts +729 -0
- package/dist/cjs/rpc-DULZzRne.d.ts +13 -0
- package/dist/cjs/scheme-7ehldYoO.d.ts +307 -0
- package/dist/cjs/scheme-BjBJzHF7.d.ts +307 -0
- package/dist/cjs/scheme-DWgpkDgz.d.ts +47 -0
- package/dist/cjs/signer-BFelv8DL.d.ts +170 -0
- package/dist/cjs/storage-6W5MO46W.d.ts +50 -0
- package/dist/cjs/storage-CHNote8s.d.ts +81 -0
- package/dist/cjs/storage-DjCv5IPh.d.ts +81 -0
- package/dist/cjs/types-CKd3Xoi1.d.ts +180 -0
- package/dist/cjs/types-DIt9uAUy.d.ts +180 -0
- package/dist/cjs/upto/client/index.d.ts +34 -0
- package/dist/cjs/upto/client/index.js +509 -0
- package/dist/cjs/upto/client/index.js.map +1 -0
- package/dist/cjs/upto/facilitator/index.d.ts +54 -0
- package/dist/cjs/upto/facilitator/index.js +1313 -0
- package/dist/cjs/upto/facilitator/index.js.map +1 -0
- package/dist/cjs/upto/server/index.d.ts +69 -0
- package/dist/cjs/upto/server/index.js +296 -0
- package/dist/cjs/upto/server/index.js.map +1 -0
- package/dist/cjs/v1/index.d.ts +40 -0
- package/dist/cjs/v1/index.js +199 -0
- package/dist/cjs/v1/index.js.map +1 -0
- package/dist/esm/auth-capture/client/index.d.mts +44 -0
- package/dist/esm/auth-capture/client/index.mjs +8 -0
- package/dist/esm/auth-capture/client/index.mjs.map +1 -0
- package/dist/esm/batch-settlement/client/file-storage.d.mts +47 -0
- package/dist/esm/batch-settlement/client/file-storage.mjs +63 -0
- package/dist/esm/batch-settlement/client/file-storage.mjs.map +1 -0
- package/dist/esm/batch-settlement/client/index.d.mts +111 -0
- package/dist/esm/batch-settlement/client/index.mjs +58 -0
- package/dist/esm/batch-settlement/client/index.mjs.map +1 -0
- package/dist/esm/batch-settlement/facilitator/index.d.mts +72 -0
- package/dist/esm/batch-settlement/facilitator/index.mjs +1252 -0
- package/dist/esm/batch-settlement/facilitator/index.mjs.map +1 -0
- package/dist/esm/batch-settlement/server/file-storage.d.mts +53 -0
- package/dist/esm/batch-settlement/server/file-storage.mjs +128 -0
- package/dist/esm/batch-settlement/server/file-storage.mjs.map +1 -0
- package/dist/esm/batch-settlement/server/index.d.mts +491 -0
- package/dist/esm/batch-settlement/server/index.mjs +1640 -0
- package/dist/esm/batch-settlement/server/index.mjs.map +1 -0
- package/dist/esm/batch-settlement/server/redis-storage.d.mts +87 -0
- package/dist/esm/batch-settlement/server/redis-storage.mjs +156 -0
- package/dist/esm/batch-settlement/server/redis-storage.mjs.map +1 -0
- package/dist/esm/chunk-2EUQTNJO.mjs +38 -0
- package/dist/esm/chunk-2EUQTNJO.mjs.map +1 -0
- package/dist/esm/chunk-3WZF6722.mjs +36 -0
- package/dist/esm/chunk-3WZF6722.mjs.map +1 -0
- package/dist/esm/chunk-E4Z7PNXC.mjs +275 -0
- package/dist/esm/chunk-E4Z7PNXC.mjs.map +1 -0
- package/dist/esm/chunk-GQVMVP4N.mjs +911 -0
- package/dist/esm/chunk-GQVMVP4N.mjs.map +1 -0
- package/dist/esm/chunk-H2EYJIZL.mjs +489 -0
- package/dist/esm/chunk-H2EYJIZL.mjs.map +1 -0
- package/dist/esm/chunk-H3KPLYGI.mjs +152 -0
- package/dist/esm/chunk-H3KPLYGI.mjs.map +1 -0
- package/dist/esm/chunk-HYABYUBD.mjs +432 -0
- package/dist/esm/chunk-HYABYUBD.mjs.map +1 -0
- package/dist/esm/chunk-I2DVUHM5.mjs +123 -0
- package/dist/esm/chunk-I2DVUHM5.mjs.map +1 -0
- package/dist/esm/chunk-JK7SLLF7.mjs +34 -0
- package/dist/esm/chunk-JK7SLLF7.mjs.map +1 -0
- package/dist/esm/chunk-JNT7C46S.mjs +352 -0
- package/dist/esm/chunk-JNT7C46S.mjs.map +1 -0
- package/dist/esm/chunk-MACPBXCT.mjs +415 -0
- package/dist/esm/chunk-MACPBXCT.mjs.map +1 -0
- package/dist/esm/chunk-P3QOX3QZ.mjs +113 -0
- package/dist/esm/chunk-P3QOX3QZ.mjs.map +1 -0
- package/dist/esm/chunk-QVATVA3J.mjs +47 -0
- package/dist/esm/chunk-QVATVA3J.mjs.map +1 -0
- package/dist/esm/chunk-SHJFA25H.mjs +159 -0
- package/dist/esm/chunk-SHJFA25H.mjs.map +1 -0
- package/dist/esm/chunk-TW7Z65AO.mjs +34 -0
- package/dist/esm/chunk-TW7Z65AO.mjs.map +1 -0
- package/dist/esm/chunk-U4HCGTLU.mjs +35 -0
- package/dist/esm/chunk-U4HCGTLU.mjs.map +1 -0
- package/dist/esm/chunk-VS3RYAYE.mjs +80 -0
- package/dist/esm/chunk-VS3RYAYE.mjs.map +1 -0
- package/dist/esm/chunk-W6ON4LG2.mjs +39 -0
- package/dist/esm/chunk-W6ON4LG2.mjs.map +1 -0
- package/dist/esm/chunk-XG2JLZVJ.mjs +627 -0
- package/dist/esm/chunk-XG2JLZVJ.mjs.map +1 -0
- package/dist/esm/chunk-ZCJRY5LQ.mjs +162 -0
- package/dist/esm/chunk-ZCJRY5LQ.mjs.map +1 -0
- package/dist/esm/client/agent-wallet.d.mts +69 -0
- package/dist/esm/client/agent-wallet.mjs +36 -0
- package/dist/esm/client/agent-wallet.mjs.map +1 -0
- package/dist/esm/exact/client/index.d.mts +63 -0
- package/dist/esm/exact/client/index.mjs +25 -0
- package/dist/esm/exact/client/index.mjs.map +1 -0
- package/dist/esm/exact/facilitator/index.d.mts +141 -0
- package/dist/esm/exact/facilitator/index.mjs +694 -0
- package/dist/esm/exact/facilitator/index.mjs.map +1 -0
- package/dist/esm/exact/server/index.d.mts +118 -0
- package/dist/esm/exact/server/index.mjs +153 -0
- package/dist/esm/exact/server/index.mjs.map +1 -0
- package/dist/esm/exact/v1/client/index.d.mts +38 -0
- package/dist/esm/exact/v1/client/index.mjs +12 -0
- package/dist/esm/exact/v1/client/index.mjs.map +1 -0
- package/dist/esm/exact/v1/facilitator/index.d.mts +84 -0
- package/dist/esm/exact/v1/facilitator/index.mjs +12 -0
- package/dist/esm/exact/v1/facilitator/index.mjs.map +1 -0
- package/dist/esm/facilitator/agent-wallet.d.mts +109 -0
- package/dist/esm/facilitator/agent-wallet.mjs +74 -0
- package/dist/esm/facilitator/agent-wallet.mjs.map +1 -0
- package/dist/esm/index.d.mts +338 -0
- package/dist/esm/index.mjs +144 -0
- package/dist/esm/index.mjs.map +1 -0
- package/dist/esm/permit2-DhJRUcgY.d.mts +729 -0
- package/dist/esm/rpc-DULZzRne.d.mts +13 -0
- package/dist/esm/scheme-CkNhpXrG.d.mts +307 -0
- package/dist/esm/scheme-D8ZbykGV.d.mts +47 -0
- package/dist/esm/signer-BFelv8DL.d.mts +170 -0
- package/dist/esm/storage-6W5MO46W.d.mts +50 -0
- package/dist/esm/storage-BEzTEiUr.d.mts +81 -0
- package/dist/esm/types-DIt9uAUy.d.mts +180 -0
- package/dist/esm/upto/client/index.d.mts +34 -0
- package/dist/esm/upto/client/index.mjs +22 -0
- package/dist/esm/upto/client/index.mjs.map +1 -0
- package/dist/esm/upto/facilitator/index.d.mts +54 -0
- package/dist/esm/upto/facilitator/index.mjs +507 -0
- package/dist/esm/upto/facilitator/index.mjs.map +1 -0
- package/dist/esm/upto/server/index.d.mts +69 -0
- package/dist/esm/upto/server/index.mjs +124 -0
- package/dist/esm/upto/server/index.mjs.map +1 -0
- package/dist/esm/v1/index.d.mts +40 -0
- package/dist/esm/v1/index.mjs +18 -0
- package/dist/esm/v1/index.mjs.map +1 -0
- package/package.json +250 -0
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import {
|
|
2
|
+
BATCH_SETTLEMENT_ADDRESS,
|
|
3
|
+
ErrChannelIdMismatch,
|
|
4
|
+
ErrReceiverAuthorizerMismatch,
|
|
5
|
+
ErrReceiverMismatch,
|
|
6
|
+
ErrRpcReadFailed,
|
|
7
|
+
ErrTokenMismatch,
|
|
8
|
+
ErrValidAfterInFuture,
|
|
9
|
+
ErrValidBeforeExpired,
|
|
10
|
+
ErrWithdrawDelayMismatch,
|
|
11
|
+
ErrWithdrawDelayOutOfRange,
|
|
12
|
+
MAX_WITHDRAW_DELAY,
|
|
13
|
+
MIN_WITHDRAW_DELAY,
|
|
14
|
+
batchSettlementABI,
|
|
15
|
+
claimBatchTypes,
|
|
16
|
+
computeChannelId,
|
|
17
|
+
getBatchSettlementEip712Domain,
|
|
18
|
+
refundTypes,
|
|
19
|
+
voucherTypes
|
|
20
|
+
} from "./chunk-HYABYUBD.mjs";
|
|
21
|
+
import {
|
|
22
|
+
multicall
|
|
23
|
+
} from "./chunk-VS3RYAYE.mjs";
|
|
24
|
+
import {
|
|
25
|
+
getEvmChainId
|
|
26
|
+
} from "./chunk-TW7Z65AO.mjs";
|
|
27
|
+
|
|
28
|
+
// src/batch-settlement/authorizerSigner.ts
|
|
29
|
+
async function signClaimBatch(signer, claims, network) {
|
|
30
|
+
const chainId = getEvmChainId(network);
|
|
31
|
+
const claimEntries = claims.map((c) => ({
|
|
32
|
+
channelId: computeChannelId(c.voucher.channel, chainId),
|
|
33
|
+
maxClaimableAmount: BigInt(c.voucher.maxClaimableAmount),
|
|
34
|
+
totalClaimed: BigInt(c.totalClaimed)
|
|
35
|
+
}));
|
|
36
|
+
return signer.signTypedData({
|
|
37
|
+
domain: getBatchSettlementEip712Domain(chainId),
|
|
38
|
+
types: claimBatchTypes,
|
|
39
|
+
primaryType: "ClaimBatch",
|
|
40
|
+
message: {
|
|
41
|
+
claims: claimEntries
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
async function signRefund(signer, channelId, amount, nonce, network) {
|
|
46
|
+
const chainId = getEvmChainId(network);
|
|
47
|
+
return signer.signTypedData({
|
|
48
|
+
domain: getBatchSettlementEip712Domain(chainId),
|
|
49
|
+
types: refundTypes,
|
|
50
|
+
primaryType: "Refund",
|
|
51
|
+
message: {
|
|
52
|
+
channelId,
|
|
53
|
+
nonce: BigInt(nonce),
|
|
54
|
+
amount: BigInt(amount)
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// src/batch-settlement/facilitator/utils.ts
|
|
60
|
+
import { getAddress, verifyTypedData as viemVerifyTypedData } from "viem";
|
|
61
|
+
function toContractChannelConfig(config) {
|
|
62
|
+
return {
|
|
63
|
+
payer: getAddress(config.payer),
|
|
64
|
+
payerAuthorizer: getAddress(config.payerAuthorizer),
|
|
65
|
+
receiver: getAddress(config.receiver),
|
|
66
|
+
receiverAuthorizer: getAddress(config.receiverAuthorizer),
|
|
67
|
+
token: getAddress(config.token),
|
|
68
|
+
withdrawDelay: config.withdrawDelay,
|
|
69
|
+
salt: config.salt
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
function erc3009AuthorizationTimeInvalidReason(validAfter, validBefore) {
|
|
73
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
74
|
+
if (validBefore < BigInt(now + 6)) return ErrValidBeforeExpired;
|
|
75
|
+
if (validAfter > BigInt(now)) return ErrValidAfterInFuture;
|
|
76
|
+
return void 0;
|
|
77
|
+
}
|
|
78
|
+
async function verifyBatchSettlementVoucherTypedData(signer, params, chainId) {
|
|
79
|
+
const domain = getBatchSettlementEip712Domain(chainId);
|
|
80
|
+
const message = {
|
|
81
|
+
channelId: params.channelId,
|
|
82
|
+
maxClaimableAmount: BigInt(params.maxClaimableAmount)
|
|
83
|
+
};
|
|
84
|
+
const zeroAddress = "0x0000000000000000000000000000000000000000";
|
|
85
|
+
if (params.payerAuthorizer !== zeroAddress) {
|
|
86
|
+
return viemVerifyTypedData({
|
|
87
|
+
address: getAddress(params.payerAuthorizer),
|
|
88
|
+
domain,
|
|
89
|
+
types: voucherTypes,
|
|
90
|
+
primaryType: "Voucher",
|
|
91
|
+
message,
|
|
92
|
+
signature: params.signature
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
return signer.verifyTypedData({
|
|
96
|
+
address: getAddress(params.payer),
|
|
97
|
+
domain,
|
|
98
|
+
types: voucherTypes,
|
|
99
|
+
primaryType: "Voucher",
|
|
100
|
+
message,
|
|
101
|
+
signature: params.signature
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
function validateChannelConfig(config, channelId, requirements) {
|
|
105
|
+
const computedId = computeChannelId(config, requirements.network);
|
|
106
|
+
if (computedId.toLowerCase() !== channelId.toLowerCase()) {
|
|
107
|
+
return ErrChannelIdMismatch;
|
|
108
|
+
}
|
|
109
|
+
if (getAddress(config.receiver) !== getAddress(requirements.payTo)) {
|
|
110
|
+
return ErrReceiverMismatch;
|
|
111
|
+
}
|
|
112
|
+
const extra = requirements.extra;
|
|
113
|
+
const requiredReceiverAuthorizer = extra?.receiverAuthorizer;
|
|
114
|
+
if (!requiredReceiverAuthorizer || getAddress(requiredReceiverAuthorizer) === "0x0000000000000000000000000000000000000000" || getAddress(config.receiverAuthorizer) !== getAddress(requiredReceiverAuthorizer)) {
|
|
115
|
+
return ErrReceiverAuthorizerMismatch;
|
|
116
|
+
}
|
|
117
|
+
if (getAddress(config.token) !== getAddress(requirements.asset)) {
|
|
118
|
+
return ErrTokenMismatch;
|
|
119
|
+
}
|
|
120
|
+
if (extra?.withdrawDelay !== void 0 && config.withdrawDelay !== Number(extra.withdrawDelay)) {
|
|
121
|
+
return ErrWithdrawDelayMismatch;
|
|
122
|
+
}
|
|
123
|
+
if (config.withdrawDelay < MIN_WITHDRAW_DELAY || config.withdrawDelay > MAX_WITHDRAW_DELAY) {
|
|
124
|
+
return ErrWithdrawDelayOutOfRange;
|
|
125
|
+
}
|
|
126
|
+
return void 0;
|
|
127
|
+
}
|
|
128
|
+
async function readChannelState(signer, channelId) {
|
|
129
|
+
const target = getAddress(BATCH_SETTLEMENT_ADDRESS);
|
|
130
|
+
const mcResults = await multicall(signer.readContract.bind(signer), [
|
|
131
|
+
{ address: target, abi: batchSettlementABI, functionName: "channels", args: [channelId] },
|
|
132
|
+
{
|
|
133
|
+
address: target,
|
|
134
|
+
abi: batchSettlementABI,
|
|
135
|
+
functionName: "pendingWithdrawals",
|
|
136
|
+
args: [channelId]
|
|
137
|
+
},
|
|
138
|
+
{ address: target, abi: batchSettlementABI, functionName: "refundNonce", args: [channelId] }
|
|
139
|
+
]);
|
|
140
|
+
const [chRes, wdRes, rnRes] = mcResults;
|
|
141
|
+
if (chRes.status === "failure" || wdRes.status === "failure" || rnRes.status === "failure") {
|
|
142
|
+
throw new Error(`${ErrRpcReadFailed}: multicall returned failure for ${channelId}`);
|
|
143
|
+
}
|
|
144
|
+
const [balance, totalClaimed] = chRes.result;
|
|
145
|
+
const [, wdInitiatedAt] = wdRes.result;
|
|
146
|
+
const refundNonce = rnRes.result;
|
|
147
|
+
return { balance, totalClaimed, withdrawRequestedAt: Number(wdInitiatedAt), refundNonce };
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
export {
|
|
151
|
+
signClaimBatch,
|
|
152
|
+
signRefund,
|
|
153
|
+
toContractChannelConfig,
|
|
154
|
+
erc3009AuthorizationTimeInvalidReason,
|
|
155
|
+
verifyBatchSettlementVoucherTypedData,
|
|
156
|
+
validateChannelConfig,
|
|
157
|
+
readChannelState
|
|
158
|
+
};
|
|
159
|
+
//# sourceMappingURL=chunk-SHJFA25H.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/batch-settlement/authorizerSigner.ts","../../src/batch-settlement/facilitator/utils.ts"],"sourcesContent":["import type { AuthorizerSigner, BatchSettlementVoucherClaim } from \"./types\";\nimport { claimBatchTypes, refundTypes } from \"./constants\";\nimport { computeChannelId, getBatchSettlementEip712Domain } from \"./utils\";\nimport { getEvmChainId } from \"../utils\";\n\n/**\n * Signs a `ClaimBatch` EIP-712 digest for `claimWithSignature()`.\n *\n * @param signer - Authorizer signer holding the `receiverAuthorizer` key.\n * @param claims - Voucher claims to include in the batch.\n * @param network - CAIP-2 network identifier (e.g. `\"eip155:84532\"`).\n * @returns EIP-712 signature over `ClaimBatch(ClaimEntry[] claims)`.\n */\nexport async function signClaimBatch(\n signer: AuthorizerSigner,\n claims: BatchSettlementVoucherClaim[],\n network: string,\n): Promise<`0x${string}`> {\n const chainId = getEvmChainId(network);\n\n const claimEntries = claims.map(c => ({\n channelId: computeChannelId(c.voucher.channel, chainId),\n maxClaimableAmount: BigInt(c.voucher.maxClaimableAmount),\n totalClaimed: BigInt(c.totalClaimed),\n }));\n\n return signer.signTypedData({\n domain: getBatchSettlementEip712Domain(chainId),\n types: claimBatchTypes,\n primaryType: \"ClaimBatch\",\n message: {\n claims: claimEntries,\n },\n });\n}\n\n/**\n * Signs a `Refund` EIP-712 digest for `refundWithSignature()`.\n *\n * @param signer - Authorizer signer holding the `receiverAuthorizer` key.\n * @param channelId - Channel to authorize refund for.\n * @param amount - Refund amount (capped to unclaimed escrow onchain).\n * @param nonce - Must match onchain `refundNonce(channelId)`.\n * @param network - CAIP-2 network identifier (e.g. `\"eip155:84532\"`).\n * @returns EIP-712 signature over `Refund(channelId, nonce, amount)`.\n */\nexport async function signRefund(\n signer: AuthorizerSigner,\n channelId: `0x${string}`,\n amount: string,\n nonce: string,\n network: string,\n): Promise<`0x${string}`> {\n const chainId = getEvmChainId(network);\n\n return signer.signTypedData({\n domain: getBatchSettlementEip712Domain(chainId),\n types: refundTypes,\n primaryType: \"Refund\",\n message: {\n channelId,\n nonce: BigInt(nonce),\n amount: BigInt(amount),\n },\n });\n}\n","import { getAddress, verifyTypedData as viemVerifyTypedData } from \"viem\";\nimport type { PaymentRequirements } from \"@bankofai/x402-core/types\";\nimport { FacilitatorEvmSigner } from \"../../signer\";\nimport { multicall } from \"../../multicall\";\nimport {\n BATCH_SETTLEMENT_ADDRESS,\n MIN_WITHDRAW_DELAY,\n MAX_WITHDRAW_DELAY,\n voucherTypes,\n} from \"../constants\";\nimport { batchSettlementABI } from \"../abi\";\nimport type {\n BatchSettlementPaymentRequirementsExtra,\n ChannelConfig,\n ChannelState,\n} from \"../types\";\nimport { computeChannelId, getBatchSettlementEip712Domain } from \"../utils\";\nimport * as Errors from \"../errors\";\n\n/**\n * Normalises a {@link ChannelConfig} into the checksummed-address tuple expected by the\n * batch-settlement contract's `deposit` / `refundWithSignature` / `claimWithSignature` calls.\n *\n * @param config - In-memory channel configuration.\n * @returns Channel config tuple with all address fields checksummed via `getAddress`.\n */\nexport function toContractChannelConfig(config: ChannelConfig) {\n return {\n payer: getAddress(config.payer),\n payerAuthorizer: getAddress(config.payerAuthorizer),\n receiver: getAddress(config.receiver),\n receiverAuthorizer: getAddress(config.receiverAuthorizer),\n token: getAddress(config.token),\n withdrawDelay: config.withdrawDelay,\n salt: config.salt,\n };\n}\n\n/**\n * Case-insensitive comparison of two channel id hex strings.\n *\n * @param a - First channel id.\n * @param b - Second channel id (may be any unknown value).\n * @returns `true` when both ids refer to the same channel.\n */\nexport function channelIdsEqual(a: `0x${string}`, b: unknown): boolean {\n if (typeof b !== \"string\" || b.length === 0) return false;\n const norm = (x: string) => {\n let s = x.toLowerCase();\n if (s.startsWith(\"0x\")) s = s.slice(2);\n return `0x${s}`;\n };\n return norm(a) === norm(b);\n}\n\n/**\n * Validates the time window of an ERC-3009 `ReceiveWithAuthorization`.\n *\n * @param validAfter - Earliest unix timestamp the authorization is valid (in seconds).\n * @param validBefore - Latest unix timestamp before which the authorization is valid.\n * @returns An error code string if the time window is invalid, otherwise `undefined`.\n */\nexport function erc3009AuthorizationTimeInvalidReason(\n validAfter: bigint,\n validBefore: bigint,\n): string | undefined {\n const now = Math.floor(Date.now() / 1000);\n if (validBefore < BigInt(now + 6)) return Errors.ErrValidBeforeExpired;\n if (validAfter > BigInt(now)) return Errors.ErrValidAfterInFuture;\n return undefined;\n}\n\n/**\n * Dual-path voucher signature verification.\n *\n * When `payerAuthorizer` is a non-zero address, the signature is verified off-chain via\n * ECDSA recovery against that address (no RPC call). When `payerAuthorizer` is `address(0)`,\n * verification falls back to an ERC-1271 `isValidSignature` call against the payer contract\n * (smart-wallet path).\n *\n * @param signer - Facilitator signer providing `verifyTypedData` (may issue RPC for ERC-1271).\n * @param params - Voucher fields and authorizer addresses needed for verification.\n * @param params.channelId - EIP-712 voucher channel id (`bytes32` hex).\n * @param params.maxClaimableAmount - Max cumulative claimable amount as a decimal string.\n * @param params.payerAuthorizer - Address that signed the voucher; zero address selects ERC-1271 verification.\n * @param params.payer - Payer contract address (used for ERC-1271).\n * @param params.signature - EIP-712 signature bytes over the voucher.\n * @param chainId - Numeric EVM chain id for the EIP-712 domain.\n * @returns `true` when the voucher signature is valid.\n */\nexport async function verifyBatchSettlementVoucherTypedData(\n signer: FacilitatorEvmSigner,\n params: {\n channelId: `0x${string}`;\n maxClaimableAmount: string;\n payerAuthorizer: `0x${string}`;\n payer: `0x${string}`;\n signature: `0x${string}`;\n },\n chainId: number,\n): Promise<boolean> {\n const domain = getBatchSettlementEip712Domain(chainId);\n const message = {\n channelId: params.channelId,\n maxClaimableAmount: BigInt(params.maxClaimableAmount),\n };\n\n const zeroAddress = \"0x0000000000000000000000000000000000000000\";\n\n if (params.payerAuthorizer !== zeroAddress) {\n return viemVerifyTypedData({\n address: getAddress(params.payerAuthorizer),\n domain,\n types: voucherTypes,\n primaryType: \"Voucher\",\n message,\n signature: params.signature,\n });\n }\n\n return signer.verifyTypedData({\n address: getAddress(params.payer),\n domain,\n types: voucherTypes,\n primaryType: \"Voucher\",\n message,\n signature: params.signature,\n });\n}\n\n/**\n * Validates that a {@link ChannelConfig} is consistent with the claimed `channelId` and\n * the server's {@link PaymentRequirements}.\n *\n * @param config - The channel configuration from the payload.\n * @param channelId - The `channelId` claimed in the payload.\n * @param requirements - Server payment requirements to cross-check against.\n * @returns An error code string if validation fails, otherwise `undefined`.\n */\nexport function validateChannelConfig(\n config: ChannelConfig,\n channelId: `0x${string}`,\n requirements: PaymentRequirements,\n): string | undefined {\n const computedId = computeChannelId(config, requirements.network);\n if (computedId.toLowerCase() !== channelId.toLowerCase()) {\n return Errors.ErrChannelIdMismatch;\n }\n\n if (getAddress(config.receiver) !== getAddress(requirements.payTo)) {\n return Errors.ErrReceiverMismatch;\n }\n\n const extra = requirements.extra as Partial<BatchSettlementPaymentRequirementsExtra> | undefined;\n const requiredReceiverAuthorizer = extra?.receiverAuthorizer;\n\n if (\n !requiredReceiverAuthorizer ||\n getAddress(requiredReceiverAuthorizer) === \"0x0000000000000000000000000000000000000000\" ||\n getAddress(config.receiverAuthorizer) !== getAddress(requiredReceiverAuthorizer)\n ) {\n return Errors.ErrReceiverAuthorizerMismatch;\n }\n\n if (getAddress(config.token) !== getAddress(requirements.asset)) {\n return Errors.ErrTokenMismatch;\n }\n\n if (extra?.withdrawDelay !== undefined && config.withdrawDelay !== Number(extra.withdrawDelay)) {\n return Errors.ErrWithdrawDelayMismatch;\n }\n\n if (config.withdrawDelay < MIN_WITHDRAW_DELAY || config.withdrawDelay > MAX_WITHDRAW_DELAY) {\n return Errors.ErrWithdrawDelayOutOfRange;\n }\n\n return undefined;\n}\n\n/**\n * Reads onchain channel state via a 3-call multicall:\n * `channels(channelId)`, `pendingWithdrawals(channelId)`, `refundNonce(channelId)`.\n *\n * Throws when any sub-call fails so callers can distinguish RPC failures\n * from missing channels (which return zero balance/totalClaimed/refundNonce).\n *\n * @param signer - Facilitator signer for onchain reads.\n * @param channelId - The `bytes32` channel id.\n * @returns Fresh {@link ChannelState}.\n */\nexport async function readChannelState(\n signer: FacilitatorEvmSigner,\n channelId: `0x${string}`,\n): Promise<ChannelState> {\n const target = getAddress(BATCH_SETTLEMENT_ADDRESS);\n const mcResults = await multicall(signer.readContract.bind(signer), [\n { address: target, abi: batchSettlementABI, functionName: \"channels\", args: [channelId] },\n {\n address: target,\n abi: batchSettlementABI,\n functionName: \"pendingWithdrawals\",\n args: [channelId],\n },\n { address: target, abi: batchSettlementABI, functionName: \"refundNonce\", args: [channelId] },\n ]);\n\n const [chRes, wdRes, rnRes] = mcResults;\n if (chRes.status === \"failure\" || wdRes.status === \"failure\" || rnRes.status === \"failure\") {\n throw new Error(`${Errors.ErrRpcReadFailed}: multicall returned failure for ${channelId}`);\n }\n\n const [balance, totalClaimed] = chRes.result as [bigint, bigint];\n const [, wdInitiatedAt] = wdRes.result as [bigint, bigint];\n const refundNonce = rnRes.result as bigint;\n\n return { balance, totalClaimed, withdrawRequestedAt: Number(wdInitiatedAt), refundNonce };\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
// src/utils.ts
|
|
2
|
+
import { toHex } from "viem";
|
|
3
|
+
function getEvmChainId(network) {
|
|
4
|
+
if (network.startsWith("eip155:")) {
|
|
5
|
+
const idStr = network.split(":")[1];
|
|
6
|
+
const chainId = parseInt(idStr, 10);
|
|
7
|
+
if (isNaN(chainId)) {
|
|
8
|
+
throw new Error(`Invalid CAIP-2 chain ID: ${network}`);
|
|
9
|
+
}
|
|
10
|
+
return chainId;
|
|
11
|
+
}
|
|
12
|
+
throw new Error(`Unsupported network format: ${network} (expected eip155:CHAIN_ID)`);
|
|
13
|
+
}
|
|
14
|
+
function getCrypto() {
|
|
15
|
+
const cryptoObj = globalThis.crypto;
|
|
16
|
+
if (!cryptoObj) {
|
|
17
|
+
throw new Error("Crypto API not available");
|
|
18
|
+
}
|
|
19
|
+
return cryptoObj;
|
|
20
|
+
}
|
|
21
|
+
function createNonce() {
|
|
22
|
+
return toHex(getCrypto().getRandomValues(new Uint8Array(32)));
|
|
23
|
+
}
|
|
24
|
+
function createPermit2Nonce() {
|
|
25
|
+
const randomBytes = getCrypto().getRandomValues(new Uint8Array(32));
|
|
26
|
+
return BigInt(toHex(randomBytes)).toString();
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export {
|
|
30
|
+
getEvmChainId,
|
|
31
|
+
createNonce,
|
|
32
|
+
createPermit2Nonce
|
|
33
|
+
};
|
|
34
|
+
//# sourceMappingURL=chunk-TW7Z65AO.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/utils.ts"],"sourcesContent":["import { toHex } from \"viem\";\n\n/**\n * Extract chain ID from a CAIP-2 network identifier (eip155:CHAIN_ID).\n *\n * @param network - The network identifier in CAIP-2 format (e.g., \"eip155:8453\")\n * @returns The numeric chain ID\n * @throws Error if the network format is invalid\n */\nexport function getEvmChainId(network: string): number {\n if (network.startsWith(\"eip155:\")) {\n const idStr = network.split(\":\")[1];\n const chainId = parseInt(idStr, 10);\n if (isNaN(chainId)) {\n throw new Error(`Invalid CAIP-2 chain ID: ${network}`);\n }\n return chainId;\n }\n\n throw new Error(`Unsupported network format: ${network} (expected eip155:CHAIN_ID)`);\n}\n\n/**\n * Get the crypto object from the global scope.\n *\n * @returns The crypto object\n * @throws Error if crypto API is not available\n */\nfunction getCrypto(): Crypto {\n const cryptoObj = globalThis.crypto as Crypto | undefined;\n if (!cryptoObj) {\n throw new Error(\"Crypto API not available\");\n }\n return cryptoObj;\n}\n\n/**\n * Create a random 32-byte nonce for EIP-3009 authorization.\n *\n * @returns A hex-encoded 32-byte nonce\n */\nexport function createNonce(): `0x${string}` {\n return toHex(getCrypto().getRandomValues(new Uint8Array(32)));\n}\n\n/**\n * Creates a random 256-bit nonce for Permit2.\n * Permit2 uses uint256 nonces (not bytes32 like EIP-3009).\n *\n * @returns A string representation of the random nonce\n */\nexport function createPermit2Nonce(): string {\n const randomBytes = getCrypto().getRandomValues(new Uint8Array(32));\n return BigInt(toHex(randomBytes)).toString();\n}\n"],"mappings":";AAAA,SAAS,aAAa;AASf,SAAS,cAAc,SAAyB;AACrD,MAAI,QAAQ,WAAW,SAAS,GAAG;AACjC,UAAM,QAAQ,QAAQ,MAAM,GAAG,EAAE,CAAC;AAClC,UAAM,UAAU,SAAS,OAAO,EAAE;AAClC,QAAI,MAAM,OAAO,GAAG;AAClB,YAAM,IAAI,MAAM,4BAA4B,OAAO,EAAE;AAAA,IACvD;AACA,WAAO;AAAA,EACT;AAEA,QAAM,IAAI,MAAM,+BAA+B,OAAO,6BAA6B;AACrF;AAQA,SAAS,YAAoB;AAC3B,QAAM,YAAY,WAAW;AAC7B,MAAI,CAAC,WAAW;AACd,UAAM,IAAI,MAAM,0BAA0B;AAAA,EAC5C;AACA,SAAO;AACT;AAOO,SAAS,cAA6B;AAC3C,SAAO,MAAM,UAAU,EAAE,gBAAgB,IAAI,WAAW,EAAE,CAAC,CAAC;AAC9D;AAQO,SAAS,qBAA6B;AAC3C,QAAM,cAAc,UAAU,EAAE,gBAAgB,IAAI,WAAW,EAAE,CAAC;AAClE,SAAO,OAAO,MAAM,WAAW,CAAC,EAAE,SAAS;AAC7C;","names":[]}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
// src/batch-settlement/types.ts
|
|
2
|
+
function isObject(payload) {
|
|
3
|
+
return typeof payload === "object" && payload !== null;
|
|
4
|
+
}
|
|
5
|
+
function isVoucherFields(payload) {
|
|
6
|
+
return isObject(payload) && "channelId" in payload && "maxClaimableAmount" in payload && "signature" in payload;
|
|
7
|
+
}
|
|
8
|
+
function isBatchSettlementDepositPayload(payload) {
|
|
9
|
+
return isObject(payload) && payload.type === "deposit" && "channelConfig" in payload && isVoucherFields(payload.voucher) && isObject(payload.deposit) && typeof payload.deposit.amount === "string" && isObject(payload.deposit.authorization);
|
|
10
|
+
}
|
|
11
|
+
function isBatchSettlementVoucherPayload(payload) {
|
|
12
|
+
return isObject(payload) && payload.type === "voucher" && "channelConfig" in payload && isVoucherFields(payload.voucher);
|
|
13
|
+
}
|
|
14
|
+
function isBatchSettlementRefundPayload(payload) {
|
|
15
|
+
return isObject(payload) && payload.type === "refund" && "channelConfig" in payload && isVoucherFields(payload.voucher);
|
|
16
|
+
}
|
|
17
|
+
function isBatchSettlementClaimPayload(payload) {
|
|
18
|
+
return isObject(payload) && payload.type === "claim" && "claims" in payload;
|
|
19
|
+
}
|
|
20
|
+
function isBatchSettlementSettlePayload(payload) {
|
|
21
|
+
return isObject(payload) && payload.type === "settle" && "receiver" in payload && "token" in payload;
|
|
22
|
+
}
|
|
23
|
+
function isBatchSettlementEnrichedRefundPayload(payload) {
|
|
24
|
+
return isBatchSettlementRefundPayload(payload) && "amount" in payload && "refundNonce" in payload && "claims" in payload;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export {
|
|
28
|
+
isBatchSettlementDepositPayload,
|
|
29
|
+
isBatchSettlementVoucherPayload,
|
|
30
|
+
isBatchSettlementRefundPayload,
|
|
31
|
+
isBatchSettlementClaimPayload,
|
|
32
|
+
isBatchSettlementSettlePayload,
|
|
33
|
+
isBatchSettlementEnrichedRefundPayload
|
|
34
|
+
};
|
|
35
|
+
//# sourceMappingURL=chunk-U4HCGTLU.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/batch-settlement/types.ts"],"sourcesContent":["import type { TypedData } from \"viem\";\n\nexport interface AuthorizerSigner {\n address: `0x${string}`;\n signTypedData(params: {\n domain: Record<string, unknown>;\n types: TypedData;\n primaryType: string;\n message: Record<string, unknown>;\n }): Promise<`0x${string}`>;\n}\n\nexport type ChannelState = {\n balance: bigint;\n totalClaimed: bigint;\n withdrawRequestedAt: number;\n refundNonce: bigint;\n};\n\nexport type ChannelConfig = {\n payer: `0x${string}`;\n payerAuthorizer: `0x${string}`;\n receiver: `0x${string}`;\n receiverAuthorizer: `0x${string}`;\n token: `0x${string}`;\n withdrawDelay: number;\n salt: `0x${string}`;\n};\n\nexport type BatchSettlementErc3009Authorization = {\n validAfter: string;\n validBefore: string;\n salt: `0x${string}`;\n signature: `0x${string}`;\n};\n\nexport type BatchSettlementPermit2Authorization = {\n from: `0x${string}`;\n permitted: {\n token: `0x${string}`;\n amount: string;\n };\n spender: `0x${string}`;\n nonce: string;\n deadline: string;\n witness: {\n channelId: `0x${string}`;\n };\n signature: `0x${string}`;\n};\n\nexport type BatchSettlementAssetTransferMethod = \"eip3009\" | \"permit2\";\n\nexport type BatchSettlementDepositAuthorization =\n | {\n erc3009Authorization: BatchSettlementErc3009Authorization;\n permit2Authorization?: never;\n }\n | {\n erc3009Authorization?: never;\n permit2Authorization: BatchSettlementPermit2Authorization;\n };\n\nexport type BatchSettlementDepositPayload = {\n type: \"deposit\";\n channelConfig: ChannelConfig;\n voucher: BatchSettlementVoucherFields;\n deposit: {\n amount: string;\n authorization: BatchSettlementDepositAuthorization;\n };\n};\n\nexport type BatchSettlementVoucherPayload = {\n type: \"voucher\";\n channelConfig: ChannelConfig;\n voucher: BatchSettlementVoucherFields;\n};\n\nexport type BatchSettlementRefundPayload = {\n type: \"refund\";\n channelConfig: ChannelConfig;\n voucher: BatchSettlementVoucherFields;\n amount?: string;\n};\n\nexport type BatchSettlementVoucherFields = {\n channelId: `0x${string}`;\n maxClaimableAmount: string;\n signature: `0x${string}`;\n};\n\nexport type BatchSettlementVoucherClaim = {\n voucher: {\n channel: ChannelConfig;\n maxClaimableAmount: string;\n };\n signature: `0x${string}`;\n totalClaimed: string;\n};\n\nexport type BatchSettlementChannelStateExtra = {\n channelId: `0x${string}`;\n balance: string;\n totalClaimed: string;\n withdrawRequestedAt: number;\n refundNonce: string;\n chargedCumulativeAmount?: string;\n};\n\nexport type BatchSettlementVoucherStateExtra = {\n signedMaxClaimable?: string;\n signature?: `0x${string}`;\n};\n\nexport type BatchSettlementPaymentRequirementsExtra = {\n receiverAuthorizer: `0x${string}`;\n withdrawDelay: number;\n name: string;\n version: string;\n assetTransferMethod?: BatchSettlementAssetTransferMethod;\n channelState?: BatchSettlementChannelStateExtra;\n voucherState?: BatchSettlementVoucherStateExtra;\n};\n\nexport type FileChannelStorageOptions = {\n /** Root directory; channels are stored under `{directory}/{client|server}/{channelId}.json`. */\n directory: string;\n};\n\nexport type BatchSettlementPaymentResponseExtra = {\n chargedAmount?: string;\n channelState?: BatchSettlementChannelStateExtra;\n voucherState?: BatchSettlementVoucherStateExtra;\n};\n\nexport type BatchSettlementClaimPayload = {\n type: \"claim\";\n claims: BatchSettlementVoucherClaim[];\n claimAuthorizerSignature?: `0x${string}`;\n};\n\nexport type BatchSettlementSettlePayload = {\n type: \"settle\";\n receiver: `0x${string}`;\n token: `0x${string}`;\n};\n\nexport type BatchSettlementEnrichedRefundPayload = BatchSettlementRefundPayload & {\n amount: string;\n refundNonce: string;\n claims: BatchSettlementVoucherClaim[];\n refundAuthorizerSignature?: `0x${string}`;\n claimAuthorizerSignature?: `0x${string}`;\n};\n\nexport type BatchSettlementPayload =\n | BatchSettlementDepositPayload\n | BatchSettlementVoucherPayload\n | BatchSettlementRefundPayload;\n\nexport type BatchSettlementFacilitatorSettlePayload =\n | BatchSettlementDepositPayload\n | BatchSettlementClaimPayload\n | BatchSettlementSettlePayload\n | BatchSettlementEnrichedRefundPayload;\n\n/**\n * Returns true when the value is a non-null object (a usable record).\n *\n * @param payload - Value of unknown shape.\n * @returns True if `payload` is an object that can be indexed by string keys.\n */\nfunction isObject(payload: unknown): payload is Record<string, unknown> {\n return typeof payload === \"object\" && payload !== null;\n}\n\n/**\n * Type guard for internal voucher field shape (channel, amount, signature).\n *\n * @param payload - Unknown value to check.\n * @returns True if `payload` is an object with `channelId`, `maxClaimableAmount`, and `signature`.\n */\nfunction isVoucherFields(payload: unknown): payload is BatchSettlementVoucherFields {\n return (\n isObject(payload) &&\n \"channelId\" in payload &&\n \"maxClaimableAmount\" in payload &&\n \"signature\" in payload\n );\n}\n\n/**\n * Type guard for {@link BatchSettlementDepositPayload}.\n *\n * @param payload - Unknown payload to check.\n * @returns True if `payload` is a deposit payload (carries `deposit` and `voucher`).\n */\nexport function isBatchSettlementDepositPayload(\n payload: unknown,\n): payload is BatchSettlementDepositPayload {\n return (\n isObject(payload) &&\n payload.type === \"deposit\" &&\n \"channelConfig\" in payload &&\n isVoucherFields(payload.voucher) &&\n isObject(payload.deposit) &&\n typeof payload.deposit.amount === \"string\" &&\n isObject(payload.deposit.authorization)\n );\n}\n\n/**\n * Type guard for {@link BatchSettlementVoucherPayload}.\n *\n * @param payload - Unknown payload to check.\n * @returns True if `payload` is a voucher payload with channel and signature fields.\n */\nexport function isBatchSettlementVoucherPayload(\n payload: unknown,\n): payload is BatchSettlementVoucherPayload {\n return (\n isObject(payload) &&\n payload.type === \"voucher\" &&\n \"channelConfig\" in payload &&\n isVoucherFields(payload.voucher)\n );\n}\n\n/**\n * Type guard for {@link BatchSettlementRefundPayload}.\n *\n * @param payload - Unknown payload to check.\n * @returns True if `payload` is a refund payload with channel config and voucher fields.\n */\nexport function isBatchSettlementRefundPayload(\n payload: unknown,\n): payload is BatchSettlementRefundPayload {\n return (\n isObject(payload) &&\n payload.type === \"refund\" &&\n \"channelConfig\" in payload &&\n isVoucherFields(payload.voucher)\n );\n}\n\n/**\n * Type guard for {@link BatchSettlementClaimPayload}.\n *\n * @param payload - Unknown payload to check.\n * @returns True if `payload` is a settle-action `claimWithSignature` payload.\n */\nexport function isBatchSettlementClaimPayload(\n payload: unknown,\n): payload is BatchSettlementClaimPayload {\n return isObject(payload) && payload.type === \"claim\" && \"claims\" in payload;\n}\n\n/**\n * Type guard for {@link BatchSettlementSettlePayload}.\n *\n * @param payload - Unknown payload to check.\n * @returns True if `payload` is a settle-action `settle` payload.\n */\nexport function isBatchSettlementSettlePayload(\n payload: unknown,\n): payload is BatchSettlementSettlePayload {\n return (\n isObject(payload) && payload.type === \"settle\" && \"receiver\" in payload && \"token\" in payload\n );\n}\n\n/**\n * Type guard for {@link BatchSettlementEnrichedRefundPayload}.\n *\n * @param payload - Unknown payload to check.\n * @returns True if `payload` is a settle-action `refundWithSignature` payload.\n */\nexport function isBatchSettlementEnrichedRefundPayload(\n payload: unknown,\n): payload is BatchSettlementEnrichedRefundPayload {\n return (\n isBatchSettlementRefundPayload(payload) &&\n \"amount\" in payload &&\n \"refundNonce\" in payload &&\n \"claims\" in payload\n );\n}\n"],"mappings":";AA6KA,SAAS,SAAS,SAAsD;AACtE,SAAO,OAAO,YAAY,YAAY,YAAY;AACpD;AAQA,SAAS,gBAAgB,SAA2D;AAClF,SACE,SAAS,OAAO,KAChB,eAAe,WACf,wBAAwB,WACxB,eAAe;AAEnB;AAQO,SAAS,gCACd,SAC0C;AAC1C,SACE,SAAS,OAAO,KAChB,QAAQ,SAAS,aACjB,mBAAmB,WACnB,gBAAgB,QAAQ,OAAO,KAC/B,SAAS,QAAQ,OAAO,KACxB,OAAO,QAAQ,QAAQ,WAAW,YAClC,SAAS,QAAQ,QAAQ,aAAa;AAE1C;AAQO,SAAS,gCACd,SAC0C;AAC1C,SACE,SAAS,OAAO,KAChB,QAAQ,SAAS,aACjB,mBAAmB,WACnB,gBAAgB,QAAQ,OAAO;AAEnC;AAQO,SAAS,+BACd,SACyC;AACzC,SACE,SAAS,OAAO,KAChB,QAAQ,SAAS,YACjB,mBAAmB,WACnB,gBAAgB,QAAQ,OAAO;AAEnC;AAQO,SAAS,8BACd,SACwC;AACxC,SAAO,SAAS,OAAO,KAAK,QAAQ,SAAS,WAAW,YAAY;AACtE;AAQO,SAAS,+BACd,SACyC;AACzC,SACE,SAAS,OAAO,KAAK,QAAQ,SAAS,YAAY,cAAc,WAAW,WAAW;AAE1F;AAQO,SAAS,uCACd,SACiD;AACjD,SACE,+BAA+B,OAAO,KACtC,YAAY,WACZ,iBAAiB,WACjB,YAAY;AAEhB;","names":[]}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
// src/multicall.ts
|
|
2
|
+
import { encodeFunctionData, decodeFunctionResult } from "viem";
|
|
3
|
+
var MULTICALL3_ADDRESS = "0xcA11bde05977b3631167028862bE2a173976CA11";
|
|
4
|
+
var multicall3ABI = [
|
|
5
|
+
{
|
|
6
|
+
inputs: [
|
|
7
|
+
{ name: "requireSuccess", type: "bool" },
|
|
8
|
+
{
|
|
9
|
+
name: "calls",
|
|
10
|
+
type: "tuple[]",
|
|
11
|
+
components: [
|
|
12
|
+
{ name: "target", type: "address" },
|
|
13
|
+
{ name: "callData", type: "bytes" }
|
|
14
|
+
]
|
|
15
|
+
}
|
|
16
|
+
],
|
|
17
|
+
name: "tryAggregate",
|
|
18
|
+
outputs: [
|
|
19
|
+
{
|
|
20
|
+
name: "returnData",
|
|
21
|
+
type: "tuple[]",
|
|
22
|
+
components: [
|
|
23
|
+
{ name: "success", type: "bool" },
|
|
24
|
+
{ name: "returnData", type: "bytes" }
|
|
25
|
+
]
|
|
26
|
+
}
|
|
27
|
+
],
|
|
28
|
+
stateMutability: "payable",
|
|
29
|
+
type: "function"
|
|
30
|
+
}
|
|
31
|
+
];
|
|
32
|
+
async function multicall(readContract, calls) {
|
|
33
|
+
const aggregateCalls = calls.map((call) => {
|
|
34
|
+
if ("callData" in call) {
|
|
35
|
+
return { target: call.address, callData: call.callData };
|
|
36
|
+
}
|
|
37
|
+
const callData = encodeFunctionData({
|
|
38
|
+
abi: call.abi,
|
|
39
|
+
functionName: call.functionName,
|
|
40
|
+
args: call.args
|
|
41
|
+
});
|
|
42
|
+
return { target: call.address, callData };
|
|
43
|
+
});
|
|
44
|
+
const rawResults = await readContract({
|
|
45
|
+
address: MULTICALL3_ADDRESS,
|
|
46
|
+
abi: multicall3ABI,
|
|
47
|
+
functionName: "tryAggregate",
|
|
48
|
+
args: [false, aggregateCalls]
|
|
49
|
+
});
|
|
50
|
+
return rawResults.map((raw, i) => {
|
|
51
|
+
if (!raw.success) {
|
|
52
|
+
return {
|
|
53
|
+
status: "failure",
|
|
54
|
+
error: new Error(`multicall: call reverted (returnData: ${raw.returnData})`)
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
const call = calls[i];
|
|
58
|
+
if ("callData" in call) {
|
|
59
|
+
return { status: "success", result: void 0 };
|
|
60
|
+
}
|
|
61
|
+
try {
|
|
62
|
+
const decoded = decodeFunctionResult({
|
|
63
|
+
abi: call.abi,
|
|
64
|
+
functionName: call.functionName,
|
|
65
|
+
data: raw.returnData
|
|
66
|
+
});
|
|
67
|
+
return { status: "success", result: decoded };
|
|
68
|
+
} catch (err) {
|
|
69
|
+
return {
|
|
70
|
+
status: "failure",
|
|
71
|
+
error: err instanceof Error ? err : new Error(String(err))
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export {
|
|
78
|
+
multicall
|
|
79
|
+
};
|
|
80
|
+
//# sourceMappingURL=chunk-VS3RYAYE.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/multicall.ts"],"sourcesContent":["import { encodeFunctionData, decodeFunctionResult } from \"viem\";\n\n/**\n * Multicall3 contract address.\n * Same address on all EVM chains via CREATE2 deployment.\n *\n * @see https://github.com/mds1/multicall\n */\nexport const MULTICALL3_ADDRESS = \"0xcA11bde05977b3631167028862bE2a173976CA11\" as const;\n\n/** Multicall3 getEthBalance ABI for querying native token balance. */\nexport const multicall3GetEthBalanceAbi = [\n {\n name: \"getEthBalance\",\n inputs: [{ name: \"addr\", type: \"address\" }],\n outputs: [{ name: \"balance\", type: \"uint256\" }],\n stateMutability: \"view\",\n type: \"function\",\n },\n] as const;\n\n/** Multicall3 tryAggregate ABI for batching calls. */\nconst multicall3ABI = [\n {\n inputs: [\n { name: \"requireSuccess\", type: \"bool\" },\n {\n name: \"calls\",\n type: \"tuple[]\",\n components: [\n { name: \"target\", type: \"address\" },\n { name: \"callData\", type: \"bytes\" },\n ],\n },\n ],\n name: \"tryAggregate\",\n outputs: [\n {\n name: \"returnData\",\n type: \"tuple[]\",\n components: [\n { name: \"success\", type: \"bool\" },\n { name: \"returnData\", type: \"bytes\" },\n ],\n },\n ],\n stateMutability: \"payable\",\n type: \"function\",\n },\n] as const;\n\nexport type ContractCall = {\n address: `0x${string}`;\n abi: readonly unknown[];\n functionName: string;\n args?: readonly unknown[];\n};\n\nexport type RawContractCall = {\n address: `0x${string}`;\n callData: `0x${string}`;\n};\n\nexport type MulticallSuccess = { status: \"success\"; result: unknown };\nexport type MulticallFailure = { status: \"failure\"; error: Error };\nexport type MulticallResult = MulticallSuccess | MulticallFailure;\n\n/**\n * Batches contract calls via Multicall3 `tryAggregate(false, ...)`.\n *\n * Accepts a mix of typed ContractCall (ABI-encoded + decoded) and\n * RawContractCall (pre-encoded calldata, no decoding) entries.\n * Raw calls are useful for the EIP-6492 factory deployment case\n * where calldata is pre-encoded with no ABI available.\n */\ntype ReadContractFn = (args: {\n address: `0x${string}`;\n abi: readonly unknown[];\n functionName: string;\n args?: readonly unknown[];\n}) => Promise<unknown>;\n\n/**\n * Executes multiple contract read calls in a single RPC round-trip using Multicall3.\n *\n * @param readContract - Function that performs a single contract read (e.g. viem readContract)\n * @param calls - Array of contract calls to batch (ContractCall or RawContractCall)\n * @returns A promise that resolves to an array of decoded results, one per call\n */\nexport async function multicall(\n readContract: ReadContractFn,\n calls: ReadonlyArray<ContractCall | RawContractCall>,\n): Promise<MulticallResult[]> {\n const aggregateCalls = calls.map(call => {\n if (\"callData\" in call) {\n return { target: call.address, callData: call.callData };\n }\n const callData = encodeFunctionData({\n abi: call.abi,\n functionName: call.functionName,\n args: call.args as unknown[],\n });\n return { target: call.address, callData };\n });\n\n const rawResults = (await readContract({\n address: MULTICALL3_ADDRESS,\n abi: multicall3ABI,\n functionName: \"tryAggregate\",\n args: [false, aggregateCalls],\n })) as { success: boolean; returnData: `0x${string}` }[];\n\n return rawResults.map((raw, i) => {\n if (!raw.success) {\n return {\n status: \"failure\" as const,\n error: new Error(`multicall: call reverted (returnData: ${raw.returnData})`),\n };\n }\n\n const call = calls[i];\n if (\"callData\" in call) {\n return { status: \"success\" as const, result: undefined };\n }\n\n try {\n const decoded = decodeFunctionResult({\n abi: call.abi,\n functionName: call.functionName,\n data: raw.returnData,\n });\n return { status: \"success\" as const, result: decoded };\n } catch (err) {\n return {\n status: \"failure\" as const,\n error: err instanceof Error ? err : new Error(String(err)),\n };\n }\n });\n}\n"],"mappings":";AAAA,SAAS,oBAAoB,4BAA4B;AAQlD,IAAM,qBAAqB;AAclC,IAAM,gBAAgB;AAAA,EACpB;AAAA,IACE,QAAQ;AAAA,MACN,EAAE,MAAM,kBAAkB,MAAM,OAAO;AAAA,MACvC;AAAA,QACE,MAAM;AAAA,QACN,MAAM;AAAA,QACN,YAAY;AAAA,UACV,EAAE,MAAM,UAAU,MAAM,UAAU;AAAA,UAClC,EAAE,MAAM,YAAY,MAAM,QAAQ;AAAA,QACpC;AAAA,MACF;AAAA,IACF;AAAA,IACA,MAAM;AAAA,IACN,SAAS;AAAA,MACP;AAAA,QACE,MAAM;AAAA,QACN,MAAM;AAAA,QACN,YAAY;AAAA,UACV,EAAE,MAAM,WAAW,MAAM,OAAO;AAAA,UAChC,EAAE,MAAM,cAAc,MAAM,QAAQ;AAAA,QACtC;AAAA,MACF;AAAA,IACF;AAAA,IACA,iBAAiB;AAAA,IACjB,MAAM;AAAA,EACR;AACF;AAwCA,eAAsB,UACpB,cACA,OAC4B;AAC5B,QAAM,iBAAiB,MAAM,IAAI,UAAQ;AACvC,QAAI,cAAc,MAAM;AACtB,aAAO,EAAE,QAAQ,KAAK,SAAS,UAAU,KAAK,SAAS;AAAA,IACzD;AACA,UAAM,WAAW,mBAAmB;AAAA,MAClC,KAAK,KAAK;AAAA,MACV,cAAc,KAAK;AAAA,MACnB,MAAM,KAAK;AAAA,IACb,CAAC;AACD,WAAO,EAAE,QAAQ,KAAK,SAAS,SAAS;AAAA,EAC1C,CAAC;AAED,QAAM,aAAc,MAAM,aAAa;AAAA,IACrC,SAAS;AAAA,IACT,KAAK;AAAA,IACL,cAAc;AAAA,IACd,MAAM,CAAC,OAAO,cAAc;AAAA,EAC9B,CAAC;AAED,SAAO,WAAW,IAAI,CAAC,KAAK,MAAM;AAChC,QAAI,CAAC,IAAI,SAAS;AAChB,aAAO;AAAA,QACL,QAAQ;AAAA,QACR,OAAO,IAAI,MAAM,yCAAyC,IAAI,UAAU,GAAG;AAAA,MAC7E;AAAA,IACF;AAEA,UAAM,OAAO,MAAM,CAAC;AACpB,QAAI,cAAc,MAAM;AACtB,aAAO,EAAE,QAAQ,WAAoB,QAAQ,OAAU;AAAA,IACzD;AAEA,QAAI;AACF,YAAM,UAAU,qBAAqB;AAAA,QACnC,KAAK,KAAK;AAAA,QACV,cAAc,KAAK;AAAA,QACnB,MAAM,IAAI;AAAA,MACZ,CAAC;AACD,aAAO,EAAE,QAAQ,WAAoB,QAAQ,QAAQ;AAAA,IACvD,SAAS,KAAK;AACZ,aAAO;AAAA,QACL,QAAQ;AAAA,QACR,OAAO,eAAe,QAAQ,MAAM,IAAI,MAAM,OAAO,GAAG,CAAC;AAAA,MAC3D;AAAA,IACF;AAAA,EACF,CAAC;AACH;","names":[]}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
// src/batch-settlement/encoding.ts
|
|
2
|
+
import { encodeAbiParameters, keccak256 } from "viem";
|
|
3
|
+
function buildErc3009DepositNonce(channelId, salt) {
|
|
4
|
+
return keccak256(
|
|
5
|
+
encodeAbiParameters([{ type: "bytes32" }, { type: "uint256" }], [channelId, BigInt(salt)])
|
|
6
|
+
);
|
|
7
|
+
}
|
|
8
|
+
function buildErc3009CollectorData(validAfter, validBefore, salt, signature) {
|
|
9
|
+
return encodeAbiParameters(
|
|
10
|
+
[{ type: "uint256" }, { type: "uint256" }, { type: "uint256" }, { type: "bytes" }],
|
|
11
|
+
[BigInt(validAfter), BigInt(validBefore), BigInt(salt), signature]
|
|
12
|
+
);
|
|
13
|
+
}
|
|
14
|
+
function buildEip2612PermitData(params) {
|
|
15
|
+
return encodeAbiParameters(
|
|
16
|
+
[
|
|
17
|
+
{ type: "uint256" },
|
|
18
|
+
{ type: "uint256" },
|
|
19
|
+
{ type: "uint8" },
|
|
20
|
+
{ type: "bytes32" },
|
|
21
|
+
{ type: "bytes32" }
|
|
22
|
+
],
|
|
23
|
+
[BigInt(params.value), BigInt(params.deadline), params.v, params.r, params.s]
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
function buildPermit2CollectorData(nonce, deadline, permit2Signature, eip2612PermitData = "0x") {
|
|
27
|
+
return encodeAbiParameters(
|
|
28
|
+
[{ type: "uint256" }, { type: "uint256" }, { type: "bytes" }, { type: "bytes" }],
|
|
29
|
+
[BigInt(nonce), BigInt(deadline), permit2Signature, eip2612PermitData]
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export {
|
|
34
|
+
buildErc3009DepositNonce,
|
|
35
|
+
buildErc3009CollectorData,
|
|
36
|
+
buildEip2612PermitData,
|
|
37
|
+
buildPermit2CollectorData
|
|
38
|
+
};
|
|
39
|
+
//# sourceMappingURL=chunk-W6ON4LG2.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/batch-settlement/encoding.ts"],"sourcesContent":["/**\n * @file Encoding helpers for batch-settlement deposit collectors.\n */\nimport { encodeAbiParameters, keccak256 } from \"viem\";\n\n/**\n * Computes the ERC-3009 nonce used by the deposit collector:\n * `keccak256(abi.encode(channelId, salt))`.\n *\n * @param channelId - The `bytes32` channel id binding the authorization to a channel.\n * @param salt - Random salt provided by the client to make the nonce unique per deposit.\n * @returns The `bytes32` ERC-3009 nonce.\n */\nexport function buildErc3009DepositNonce(\n channelId: `0x${string}`,\n salt: `0x${string}`,\n): `0x${string}` {\n return keccak256(\n encodeAbiParameters([{ type: \"bytes32\" }, { type: \"uint256\" }], [channelId, BigInt(salt)]),\n );\n}\n\n/**\n * Encodes the `collectorData` payload for `ERC3009DepositCollector.collect()`:\n * `abi.encode(validAfter, validBefore, salt, signature)`.\n *\n * @param validAfter - Earliest unix timestamp the authorization is valid (decimal string).\n * @param validBefore - Latest unix timestamp the authorization is valid (decimal string).\n * @param salt - Random salt provided by the client (hex string).\n * @param signature - ERC-3009 `ReceiveWithAuthorization` signature.\n * @returns ABI-encoded collector data passed to `deposit(..., collector, collectorData)`.\n */\nexport function buildErc3009CollectorData(\n validAfter: string,\n validBefore: string,\n salt: `0x${string}`,\n signature: `0x${string}`,\n): `0x${string}` {\n return encodeAbiParameters(\n [{ type: \"uint256\" }, { type: \"uint256\" }, { type: \"uint256\" }, { type: \"bytes\" }],\n [BigInt(validAfter), BigInt(validBefore), BigInt(salt), signature],\n );\n}\n\n/**\n * Encodes optional EIP-2612 permit data consumed by `Permit2DepositCollector`.\n *\n * @param params - Permit amount, deadline, and split signature fields.\n * @param params.value - Approved Permit2 allowance value.\n * @param params.deadline - EIP-2612 permit deadline.\n * @param params.v - Signature recovery id.\n * @param params.r - Signature `r` value.\n * @param params.s - Signature `s` value.\n * @returns ABI-encoded permit segment.\n */\nexport function buildEip2612PermitData(params: {\n value: string;\n deadline: string;\n v: number;\n r: `0x${string}`;\n s: `0x${string}`;\n}): `0x${string}` {\n return encodeAbiParameters(\n [\n { type: \"uint256\" },\n { type: \"uint256\" },\n { type: \"uint8\" },\n { type: \"bytes32\" },\n { type: \"bytes32\" },\n ],\n [BigInt(params.value), BigInt(params.deadline), params.v, params.r, params.s],\n );\n}\n\n/**\n * Encodes the `collectorData` payload for `Permit2DepositCollector.collect()`.\n *\n * @param nonce - Permit2 transfer nonce.\n * @param deadline - Permit2 transfer deadline.\n * @param permit2Signature - Signature over the channel-bound Permit2 authorization.\n * @param eip2612PermitData - Optional encoded EIP-2612 permit segment.\n * @returns ABI-encoded collector data passed to `deposit`.\n */\nexport function buildPermit2CollectorData(\n nonce: string,\n deadline: string,\n permit2Signature: `0x${string}`,\n eip2612PermitData: `0x${string}` = \"0x\",\n): `0x${string}` {\n return encodeAbiParameters(\n [{ type: \"uint256\" }, { type: \"uint256\" }, { type: \"bytes\" }, { type: \"bytes\" }],\n [BigInt(nonce), BigInt(deadline), permit2Signature, eip2612PermitData],\n );\n}\n"],"mappings":";AAGA,SAAS,qBAAqB,iBAAiB;AAUxC,SAAS,yBACd,WACA,MACe;AACf,SAAO;AAAA,IACL,oBAAoB,CAAC,EAAE,MAAM,UAAU,GAAG,EAAE,MAAM,UAAU,CAAC,GAAG,CAAC,WAAW,OAAO,IAAI,CAAC,CAAC;AAAA,EAC3F;AACF;AAYO,SAAS,0BACd,YACA,aACA,MACA,WACe;AACf,SAAO;AAAA,IACL,CAAC,EAAE,MAAM,UAAU,GAAG,EAAE,MAAM,UAAU,GAAG,EAAE,MAAM,UAAU,GAAG,EAAE,MAAM,QAAQ,CAAC;AAAA,IACjF,CAAC,OAAO,UAAU,GAAG,OAAO,WAAW,GAAG,OAAO,IAAI,GAAG,SAAS;AAAA,EACnE;AACF;AAaO,SAAS,uBAAuB,QAMrB;AAChB,SAAO;AAAA,IACL;AAAA,MACE,EAAE,MAAM,UAAU;AAAA,MAClB,EAAE,MAAM,UAAU;AAAA,MAClB,EAAE,MAAM,QAAQ;AAAA,MAChB,EAAE,MAAM,UAAU;AAAA,MAClB,EAAE,MAAM,UAAU;AAAA,IACpB;AAAA,IACA,CAAC,OAAO,OAAO,KAAK,GAAG,OAAO,OAAO,QAAQ,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,CAAC;AAAA,EAC9E;AACF;AAWO,SAAS,0BACd,OACA,UACA,kBACA,oBAAmC,MACpB;AACf,SAAO;AAAA,IACL,CAAC,EAAE,MAAM,UAAU,GAAG,EAAE,MAAM,UAAU,GAAG,EAAE,MAAM,QAAQ,GAAG,EAAE,MAAM,QAAQ,CAAC;AAAA,IAC/E,CAAC,OAAO,KAAK,GAAG,OAAO,QAAQ,GAAG,kBAAkB,iBAAiB;AAAA,EACvE;AACF;","names":[]}
|