@agenticprimitives/payments 0.0.0-alpha.4 → 0.0.0-alpha.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/entitlement/index.d.ts +92 -0
- package/dist/entitlement/index.d.ts.map +1 -0
- package/dist/entitlement/index.js +93 -0
- package/dist/entitlement/index.js.map +1 -0
- package/dist/entitlement/voucher.d.ts +78 -0
- package/dist/entitlement/voucher.d.ts.map +1 -0
- package/dist/entitlement/voucher.js +102 -0
- package/dist/entitlement/voucher.js.map +1 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +18 -0
- package/dist/index.js.map +1 -1
- package/dist/mandate-sign.d.ts +173 -0
- package/dist/mandate-sign.d.ts.map +1 -0
- package/dist/mandate-sign.js +147 -0
- package/dist/mandate-sign.js.map +1 -0
- package/dist/mandate.d.ts +33 -0
- package/dist/mandate.d.ts.map +1 -0
- package/dist/mandate.js +40 -0
- package/dist/mandate.js.map +1 -0
- package/dist/ops.d.ts +55 -0
- package/dist/ops.d.ts.map +1 -0
- package/dist/ops.js +66 -0
- package/dist/ops.js.map +1 -0
- package/dist/rails/escrow.d.ts +143 -0
- package/dist/rails/escrow.d.ts.map +1 -0
- package/dist/rails/escrow.js +90 -0
- package/dist/rails/escrow.js.map +1 -0
- package/dist/rails/invoice.d.ts +65 -0
- package/dist/rails/invoice.d.ts.map +1 -0
- package/dist/rails/invoice.js +57 -0
- package/dist/rails/invoice.js.map +1 -0
- package/dist/rails/recurring.d.ts +56 -0
- package/dist/rails/recurring.d.ts.map +1 -0
- package/dist/rails/recurring.js +58 -0
- package/dist/rails/recurring.js.map +1 -0
- package/dist/rails/wallet.d.ts +16 -0
- package/dist/rails/wallet.d.ts.map +1 -0
- package/dist/rails/wallet.js +20 -0
- package/dist/rails/wallet.js.map +1 -0
- package/dist/rails/x402/executor.d.ts +17 -1
- package/dist/rails/x402/executor.d.ts.map +1 -1
- package/dist/rails/x402/executor.js +24 -2
- package/dist/rails/x402/executor.js.map +1 -1
- package/dist/receipt.d.ts +36 -0
- package/dist/receipt.d.ts.map +1 -0
- package/dist/receipt.js +50 -0
- package/dist/receipt.js.map +1 -0
- package/dist/refund.d.ts +29 -0
- package/dist/refund.d.ts.map +1 -0
- package/dist/refund.js +19 -0
- package/dist/refund.js.map +1 -0
- package/dist/split.d.ts +27 -0
- package/dist/split.d.ts.map +1 -0
- package/dist/split.js +33 -0
- package/dist/split.js.map +1 -0
- package/dist/transfer.d.ts +51 -0
- package/dist/transfer.d.ts.map +1 -0
- package/dist/transfer.js +54 -0
- package/dist/transfer.js.map +1 -0
- package/package.json +6 -5
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PMT-INV-02 / PMT-INV-12 — EIP-712 mandate signing + ERC-1271 verification.
|
|
3
|
+
*
|
|
4
|
+
* The payer SA signs an EIP-712 typed-data digest of the mandate. The signed
|
|
5
|
+
* struct flattens the load-bearing fields and folds the entire `ContextBinding`
|
|
6
|
+
* into one `contextBindingHash` — so no field can be stripped or substituted
|
|
7
|
+
* after signing (PMT-INV-02 / INV-07 / INV-08), and verification is one
|
|
8
|
+
* ERC-1271 call against the payer SA (PMT-INV-12 — no raw EOA signatures).
|
|
9
|
+
*
|
|
10
|
+
* Pure crypto only (viem) — the actual ERC-1271 read is injected so the package
|
|
11
|
+
* stays transport-agnostic (no hard publicClient dependency).
|
|
12
|
+
*/
|
|
13
|
+
import { type Address, type Hex } from 'viem';
|
|
14
|
+
import type { PaymentMandate, ContextBinding, Hex32 } from './index.js';
|
|
15
|
+
export declare const PAYMENT_MANDATE_DOMAIN_NAME = "AgenticPaymentMandate";
|
|
16
|
+
export declare const PAYMENT_MANDATE_DOMAIN_VERSION = "1";
|
|
17
|
+
/** ERC-1271 magic value for a valid signature. */
|
|
18
|
+
export declare const ERC1271_MAGIC = "0x1626ba7e";
|
|
19
|
+
export declare const PAYMENT_MANDATE_EIP712_TYPES: {
|
|
20
|
+
readonly PaymentMandate: readonly [{
|
|
21
|
+
readonly name: "mandateId";
|
|
22
|
+
readonly type: "bytes32";
|
|
23
|
+
}, {
|
|
24
|
+
readonly name: "payer";
|
|
25
|
+
readonly type: "address";
|
|
26
|
+
}, {
|
|
27
|
+
readonly name: "payee";
|
|
28
|
+
readonly type: "address";
|
|
29
|
+
}, {
|
|
30
|
+
readonly name: "granter";
|
|
31
|
+
readonly type: "address";
|
|
32
|
+
}, {
|
|
33
|
+
readonly name: "asset";
|
|
34
|
+
readonly type: "address";
|
|
35
|
+
}, {
|
|
36
|
+
readonly name: "amount";
|
|
37
|
+
readonly type: "uint256";
|
|
38
|
+
}, {
|
|
39
|
+
readonly name: "nonce";
|
|
40
|
+
readonly type: "uint256";
|
|
41
|
+
}, {
|
|
42
|
+
readonly name: "maxRedemptions";
|
|
43
|
+
readonly type: "uint256";
|
|
44
|
+
}, {
|
|
45
|
+
readonly name: "validFrom";
|
|
46
|
+
readonly type: "uint256";
|
|
47
|
+
}, {
|
|
48
|
+
readonly name: "expiresAt";
|
|
49
|
+
readonly type: "uint256";
|
|
50
|
+
}, {
|
|
51
|
+
readonly name: "mode";
|
|
52
|
+
readonly type: "string";
|
|
53
|
+
}, {
|
|
54
|
+
readonly name: "rail";
|
|
55
|
+
readonly type: "string";
|
|
56
|
+
}, {
|
|
57
|
+
readonly name: "reasonHash";
|
|
58
|
+
readonly type: "bytes32";
|
|
59
|
+
}, {
|
|
60
|
+
readonly name: "contextBindingHash";
|
|
61
|
+
readonly type: "bytes32";
|
|
62
|
+
}];
|
|
63
|
+
};
|
|
64
|
+
/** The charge amount carried by the mandate (exact → amount; range/formula → maxAmount). */
|
|
65
|
+
export declare function mandateAmount(mandate: PaymentMandate): bigint;
|
|
66
|
+
/**
|
|
67
|
+
* Canonical hash of the ENTIRE context binding (PMT-INV-02). Every field is
|
|
68
|
+
* folded in; absent fields hash to zero, so adding/removing one changes the hash.
|
|
69
|
+
*/
|
|
70
|
+
export declare function hashContextBinding(cb: ContextBinding): Hex32;
|
|
71
|
+
export interface MandateDomainOpts {
|
|
72
|
+
chainId: number;
|
|
73
|
+
/** Optional binding to a specific contract (e.g. the PaymentEnforcer). Omit for a chain-scoped mandate. */
|
|
74
|
+
verifyingContract?: Address;
|
|
75
|
+
}
|
|
76
|
+
export declare function paymentMandateDomain(opts: MandateDomainOpts): {
|
|
77
|
+
readonly verifyingContract?: `0x${string}` | undefined;
|
|
78
|
+
readonly name: "AgenticPaymentMandate";
|
|
79
|
+
readonly version: "1";
|
|
80
|
+
readonly chainId: number;
|
|
81
|
+
};
|
|
82
|
+
/** The full EIP-712 typed-data object (domain + types + message) for a mandate. */
|
|
83
|
+
export declare function buildPaymentMandateTypedData(mandate: PaymentMandate, opts: MandateDomainOpts): {
|
|
84
|
+
domain: {
|
|
85
|
+
readonly verifyingContract?: `0x${string}` | undefined;
|
|
86
|
+
readonly name: "AgenticPaymentMandate";
|
|
87
|
+
readonly version: "1";
|
|
88
|
+
readonly chainId: number;
|
|
89
|
+
};
|
|
90
|
+
types: {
|
|
91
|
+
readonly PaymentMandate: readonly [{
|
|
92
|
+
readonly name: "mandateId";
|
|
93
|
+
readonly type: "bytes32";
|
|
94
|
+
}, {
|
|
95
|
+
readonly name: "payer";
|
|
96
|
+
readonly type: "address";
|
|
97
|
+
}, {
|
|
98
|
+
readonly name: "payee";
|
|
99
|
+
readonly type: "address";
|
|
100
|
+
}, {
|
|
101
|
+
readonly name: "granter";
|
|
102
|
+
readonly type: "address";
|
|
103
|
+
}, {
|
|
104
|
+
readonly name: "asset";
|
|
105
|
+
readonly type: "address";
|
|
106
|
+
}, {
|
|
107
|
+
readonly name: "amount";
|
|
108
|
+
readonly type: "uint256";
|
|
109
|
+
}, {
|
|
110
|
+
readonly name: "nonce";
|
|
111
|
+
readonly type: "uint256";
|
|
112
|
+
}, {
|
|
113
|
+
readonly name: "maxRedemptions";
|
|
114
|
+
readonly type: "uint256";
|
|
115
|
+
}, {
|
|
116
|
+
readonly name: "validFrom";
|
|
117
|
+
readonly type: "uint256";
|
|
118
|
+
}, {
|
|
119
|
+
readonly name: "expiresAt";
|
|
120
|
+
readonly type: "uint256";
|
|
121
|
+
}, {
|
|
122
|
+
readonly name: "mode";
|
|
123
|
+
readonly type: "string";
|
|
124
|
+
}, {
|
|
125
|
+
readonly name: "rail";
|
|
126
|
+
readonly type: "string";
|
|
127
|
+
}, {
|
|
128
|
+
readonly name: "reasonHash";
|
|
129
|
+
readonly type: "bytes32";
|
|
130
|
+
}, {
|
|
131
|
+
readonly name: "contextBindingHash";
|
|
132
|
+
readonly type: "bytes32";
|
|
133
|
+
}];
|
|
134
|
+
};
|
|
135
|
+
primaryType: "PaymentMandate";
|
|
136
|
+
message: {
|
|
137
|
+
readonly mandateId: `0x${string}`;
|
|
138
|
+
readonly payer: `0x${string}`;
|
|
139
|
+
readonly payee: `0x${string}`;
|
|
140
|
+
readonly granter: `0x${string}`;
|
|
141
|
+
readonly asset: Address;
|
|
142
|
+
readonly amount: bigint;
|
|
143
|
+
readonly nonce: bigint;
|
|
144
|
+
readonly maxRedemptions: bigint;
|
|
145
|
+
readonly validFrom: bigint;
|
|
146
|
+
readonly expiresAt: bigint;
|
|
147
|
+
readonly mode: import("./index.js").PaymentMandateMode;
|
|
148
|
+
readonly rail: import("./index.js").PaymentRail;
|
|
149
|
+
readonly reasonHash: `0x${string}`;
|
|
150
|
+
readonly contextBindingHash: `0x${string}`;
|
|
151
|
+
};
|
|
152
|
+
};
|
|
153
|
+
/** The 32-byte EIP-712 digest the payer SA's ERC-1271 validates over. */
|
|
154
|
+
export declare function paymentMandateDigest(mandate: PaymentMandate, opts: MandateDomainOpts): Hex32;
|
|
155
|
+
/** Signer surface — an SA signer that produces an ERC-1271-validatable signature over typed data. */
|
|
156
|
+
export interface MandateSigner {
|
|
157
|
+
signTypedData(args: {
|
|
158
|
+
domain: Record<string, unknown>;
|
|
159
|
+
types: typeof PAYMENT_MANDATE_EIP712_TYPES;
|
|
160
|
+
primaryType: 'PaymentMandate';
|
|
161
|
+
message: Record<string, unknown>;
|
|
162
|
+
}): Promise<Hex>;
|
|
163
|
+
}
|
|
164
|
+
/** Sign an unsigned mandate (`signature: '0x'`) → a fully-populated mandate. */
|
|
165
|
+
export declare function signPaymentMandate(mandate: PaymentMandate, signer: MandateSigner, opts: MandateDomainOpts): Promise<PaymentMandate>;
|
|
166
|
+
/** Injected ERC-1271 read: returns the 4-byte magic from `payer.isValidSignature(digest, signature)`. */
|
|
167
|
+
export type Erc1271Reader = (account: Address, digest: Hex32, signature: Hex) => Promise<Hex>;
|
|
168
|
+
/**
|
|
169
|
+
* PMT-INV-12 — verify the mandate's signature via the payer SA's ERC-1271. Fail-closed: any read
|
|
170
|
+
* error or non-magic result is `false` (never throws on a bad signature).
|
|
171
|
+
*/
|
|
172
|
+
export declare function verifyPaymentMandateSignature(mandate: PaymentMandate, opts: MandateDomainOpts, read1271: Erc1271Reader): Promise<boolean>;
|
|
173
|
+
//# sourceMappingURL=mandate-sign.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mandate-sign.d.ts","sourceRoot":"","sources":["../src/mandate-sign.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAML,KAAK,OAAO,EACZ,KAAK,GAAG,EACT,MAAM,MAAM,CAAC;AACd,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAExE,eAAO,MAAM,2BAA2B,0BAA0B,CAAC;AACnE,eAAO,MAAM,8BAA8B,MAAM,CAAC;AAElD,kDAAkD;AAClD,eAAO,MAAM,aAAa,eAAe,CAAC;AAE1C,eAAO,MAAM,4BAA4B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiB/B,CAAC;AAKX,4FAA4F;AAC5F,wBAAgB,aAAa,CAAC,OAAO,EAAE,cAAc,GAAG,MAAM,CAG7D;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,cAAc,GAAG,KAAK,CAyC5D;AAED,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,2GAA2G;IAC3G,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,iBAAiB;;;;;EAO3D;AAqBD,mFAAmF;AACnF,wBAAgB,4BAA4B,CAAC,OAAO,EAAE,cAAc,EAAE,IAAI,EAAE,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;wBAdjD,OAAO;;;;;;;;;;;EAqBlD;AAED,yEAAyE;AACzE,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,cAAc,EAAE,IAAI,EAAE,iBAAiB,GAAG,KAAK,CAG5F;AAED,qGAAqG;AACrG,MAAM,WAAW,aAAa;IAC5B,aAAa,CAAC,IAAI,EAAE;QAClB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAChC,KAAK,EAAE,OAAO,4BAA4B,CAAC;QAC3C,WAAW,EAAE,gBAAgB,CAAC;QAC9B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KAClC,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;CAClB;AAED,gFAAgF;AAChF,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,cAAc,EACvB,MAAM,EAAE,aAAa,EACrB,IAAI,EAAE,iBAAiB,GACtB,OAAO,CAAC,cAAc,CAAC,CASzB;AAED,yGAAyG;AACzG,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,KAAK,OAAO,CAAC,GAAG,CAAC,CAAC;AAE9F;;;GAGG;AACH,wBAAsB,6BAA6B,CACjD,OAAO,EAAE,cAAc,EACvB,IAAI,EAAE,iBAAiB,EACvB,QAAQ,EAAE,aAAa,GACtB,OAAO,CAAC,OAAO,CAAC,CASlB"}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PMT-INV-02 / PMT-INV-12 — EIP-712 mandate signing + ERC-1271 verification.
|
|
3
|
+
*
|
|
4
|
+
* The payer SA signs an EIP-712 typed-data digest of the mandate. The signed
|
|
5
|
+
* struct flattens the load-bearing fields and folds the entire `ContextBinding`
|
|
6
|
+
* into one `contextBindingHash` — so no field can be stripped or substituted
|
|
7
|
+
* after signing (PMT-INV-02 / INV-07 / INV-08), and verification is one
|
|
8
|
+
* ERC-1271 call against the payer SA (PMT-INV-12 — no raw EOA signatures).
|
|
9
|
+
*
|
|
10
|
+
* Pure crypto only (viem) — the actual ERC-1271 read is injected so the package
|
|
11
|
+
* stays transport-agnostic (no hard publicClient dependency).
|
|
12
|
+
*/
|
|
13
|
+
import { hashTypedData, keccak256, encodeAbiParameters, toHex, toBytes, } from 'viem';
|
|
14
|
+
export const PAYMENT_MANDATE_DOMAIN_NAME = 'AgenticPaymentMandate';
|
|
15
|
+
export const PAYMENT_MANDATE_DOMAIN_VERSION = '1';
|
|
16
|
+
/** ERC-1271 magic value for a valid signature. */
|
|
17
|
+
export const ERC1271_MAGIC = '0x1626ba7e';
|
|
18
|
+
export const PAYMENT_MANDATE_EIP712_TYPES = {
|
|
19
|
+
PaymentMandate: [
|
|
20
|
+
{ name: 'mandateId', type: 'bytes32' },
|
|
21
|
+
{ name: 'payer', type: 'address' },
|
|
22
|
+
{ name: 'payee', type: 'address' },
|
|
23
|
+
{ name: 'granter', type: 'address' },
|
|
24
|
+
{ name: 'asset', type: 'address' },
|
|
25
|
+
{ name: 'amount', type: 'uint256' },
|
|
26
|
+
{ name: 'nonce', type: 'uint256' },
|
|
27
|
+
{ name: 'maxRedemptions', type: 'uint256' },
|
|
28
|
+
{ name: 'validFrom', type: 'uint256' },
|
|
29
|
+
{ name: 'expiresAt', type: 'uint256' },
|
|
30
|
+
{ name: 'mode', type: 'string' },
|
|
31
|
+
{ name: 'rail', type: 'string' },
|
|
32
|
+
{ name: 'reasonHash', type: 'bytes32' },
|
|
33
|
+
{ name: 'contextBindingHash', type: 'bytes32' },
|
|
34
|
+
],
|
|
35
|
+
};
|
|
36
|
+
const ZERO32 = ('0x' + '00'.repeat(32));
|
|
37
|
+
const hashStr = (s) => (s ? keccak256(toBytes(s)) : ZERO32);
|
|
38
|
+
/** The charge amount carried by the mandate (exact → amount; range/formula → maxAmount). */
|
|
39
|
+
export function mandateAmount(mandate) {
|
|
40
|
+
const ap = mandate.amountPolicy;
|
|
41
|
+
return ap.kind === 'exact' ? ap.amount : ap.maxAmount;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Canonical hash of the ENTIRE context binding (PMT-INV-02). Every field is
|
|
45
|
+
* folded in; absent fields hash to zero, so adding/removing one changes the hash.
|
|
46
|
+
*/
|
|
47
|
+
export function hashContextBinding(cb) {
|
|
48
|
+
const resourceHash = cb.resource
|
|
49
|
+
? keccak256(encodeAbiParameters([{ type: 'string' }, { type: 'string' }, { type: 'bytes32' }], [cb.resource.method, cb.resource.url, cb.resource.requestBodyHash]))
|
|
50
|
+
: ZERO32;
|
|
51
|
+
return keccak256(encodeAbiParameters([
|
|
52
|
+
{ type: 'bytes32' }, // intentIdHash
|
|
53
|
+
{ type: 'bytes32' }, // agreementCommitment
|
|
54
|
+
{ type: 'bytes32' }, // taskId
|
|
55
|
+
{ type: 'bytes32' }, // artifactHash
|
|
56
|
+
{ type: 'bytes32' }, // resourceHash
|
|
57
|
+
{ type: 'bytes32' }, // orderHash
|
|
58
|
+
{ type: 'bytes32' }, // legId
|
|
59
|
+
{ type: 'uint256' }, // chain
|
|
60
|
+
{ type: 'address' }, // asset
|
|
61
|
+
{ type: 'uint256' }, // nonce
|
|
62
|
+
{ type: 'uint256' }, // validFrom
|
|
63
|
+
{ type: 'uint256' }, // expiresAt
|
|
64
|
+
], [
|
|
65
|
+
hashStr(cb.intentId),
|
|
66
|
+
cb.agreementCommitment ?? ZERO32,
|
|
67
|
+
cb.taskId ?? ZERO32,
|
|
68
|
+
cb.artifactHash ?? ZERO32,
|
|
69
|
+
resourceHash,
|
|
70
|
+
cb.orderHash ?? ZERO32,
|
|
71
|
+
cb.legId ?? ZERO32,
|
|
72
|
+
BigInt(cb.chain),
|
|
73
|
+
cb.asset.id,
|
|
74
|
+
cb.nonce,
|
|
75
|
+
BigInt(cb.validFrom),
|
|
76
|
+
BigInt(cb.expiresAt),
|
|
77
|
+
]));
|
|
78
|
+
}
|
|
79
|
+
export function paymentMandateDomain(opts) {
|
|
80
|
+
return {
|
|
81
|
+
name: PAYMENT_MANDATE_DOMAIN_NAME,
|
|
82
|
+
version: PAYMENT_MANDATE_DOMAIN_VERSION,
|
|
83
|
+
chainId: opts.chainId,
|
|
84
|
+
...(opts.verifyingContract ? { verifyingContract: opts.verifyingContract } : {}),
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
function mandateMessage(mandate) {
|
|
88
|
+
return {
|
|
89
|
+
mandateId: mandate.mandateId,
|
|
90
|
+
payer: mandate.payer,
|
|
91
|
+
payee: mandate.payee,
|
|
92
|
+
granter: mandate.granter,
|
|
93
|
+
asset: mandate.amountPolicy.asset.id,
|
|
94
|
+
amount: mandateAmount(mandate),
|
|
95
|
+
nonce: mandate.nonce,
|
|
96
|
+
maxRedemptions: BigInt(mandate.maxRedemptions),
|
|
97
|
+
validFrom: BigInt(mandate.validFrom),
|
|
98
|
+
expiresAt: BigInt(mandate.expiresAt),
|
|
99
|
+
mode: mandate.mode,
|
|
100
|
+
rail: mandate.rail,
|
|
101
|
+
reasonHash: mandate.reasonHash,
|
|
102
|
+
contextBindingHash: hashContextBinding(mandate.contextBinding),
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
/** The full EIP-712 typed-data object (domain + types + message) for a mandate. */
|
|
106
|
+
export function buildPaymentMandateTypedData(mandate, opts) {
|
|
107
|
+
return {
|
|
108
|
+
domain: paymentMandateDomain(opts),
|
|
109
|
+
types: PAYMENT_MANDATE_EIP712_TYPES,
|
|
110
|
+
primaryType: 'PaymentMandate',
|
|
111
|
+
message: mandateMessage(mandate),
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
/** The 32-byte EIP-712 digest the payer SA's ERC-1271 validates over. */
|
|
115
|
+
export function paymentMandateDigest(mandate, opts) {
|
|
116
|
+
const td = buildPaymentMandateTypedData(mandate, opts);
|
|
117
|
+
return hashTypedData(td);
|
|
118
|
+
}
|
|
119
|
+
/** Sign an unsigned mandate (`signature: '0x'`) → a fully-populated mandate. */
|
|
120
|
+
export async function signPaymentMandate(mandate, signer, opts) {
|
|
121
|
+
const td = buildPaymentMandateTypedData(mandate, opts);
|
|
122
|
+
const signature = await signer.signTypedData({
|
|
123
|
+
domain: td.domain,
|
|
124
|
+
types: td.types,
|
|
125
|
+
primaryType: td.primaryType,
|
|
126
|
+
message: td.message,
|
|
127
|
+
});
|
|
128
|
+
return { ...mandate, signature };
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* PMT-INV-12 — verify the mandate's signature via the payer SA's ERC-1271. Fail-closed: any read
|
|
132
|
+
* error or non-magic result is `false` (never throws on a bad signature).
|
|
133
|
+
*/
|
|
134
|
+
export async function verifyPaymentMandateSignature(mandate, opts, read1271) {
|
|
135
|
+
if (!mandate.signature || mandate.signature === '0x')
|
|
136
|
+
return false;
|
|
137
|
+
const digest = paymentMandateDigest(mandate, opts);
|
|
138
|
+
try {
|
|
139
|
+
const res = await read1271(mandate.payer, digest, mandate.signature);
|
|
140
|
+
return typeof res === 'string' && res.slice(0, 10).toLowerCase() === ERC1271_MAGIC;
|
|
141
|
+
}
|
|
142
|
+
catch {
|
|
143
|
+
return false;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
void toHex; // reserved for future debug helpers
|
|
147
|
+
//# sourceMappingURL=mandate-sign.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mandate-sign.js","sourceRoot":"","sources":["../src/mandate-sign.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `buildClosedMandate` — construct an unsigned closed (one-shot) PaymentMandate.
|
|
3
|
+
*
|
|
4
|
+
* The wallet + invoice rails (and the demo) build a closed mandate, sign it via
|
|
5
|
+
* `signPaymentMandate`, then settle it with a single transfer. Closed + one-shot per
|
|
6
|
+
* PMT-10 / PMT-INV-14. `orderHash`/`legId` (EXC-R2) bind the leg to an ExchangeOrder.
|
|
7
|
+
*/
|
|
8
|
+
import type { Address } from '@agenticprimitives/types';
|
|
9
|
+
import { type PaymentMandate, type PaymentRail, type AssetRef, type Hex32 } from './index.js';
|
|
10
|
+
export interface ClosedMandateInput {
|
|
11
|
+
payer: Address;
|
|
12
|
+
payee: Address;
|
|
13
|
+
asset: AssetRef;
|
|
14
|
+
amount: bigint;
|
|
15
|
+
chain: number;
|
|
16
|
+
rail: PaymentRail;
|
|
17
|
+
nonce: bigint;
|
|
18
|
+
expiresAt: number;
|
|
19
|
+
validFrom?: number;
|
|
20
|
+
granter?: Address;
|
|
21
|
+
orderHash?: Hex32;
|
|
22
|
+
legId?: Hex32;
|
|
23
|
+
reasonHash?: Hex32;
|
|
24
|
+
resource?: {
|
|
25
|
+
method: string;
|
|
26
|
+
url: string;
|
|
27
|
+
requestBodyHash: Hex32;
|
|
28
|
+
};
|
|
29
|
+
delegationRef?: Hex32;
|
|
30
|
+
}
|
|
31
|
+
/** Build the unsigned closed mandate (signature `'0x'`); sign with `signPaymentMandate`. */
|
|
32
|
+
export declare function buildClosedMandate(input: ClosedMandateInput): PaymentMandate;
|
|
33
|
+
//# sourceMappingURL=mandate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mandate.d.ts","sourceRoot":"","sources":["../src/mandate.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,EAAoB,KAAK,cAAc,EAAE,KAAK,WAAW,EAAE,KAAK,QAAQ,EAAE,KAAK,KAAK,EAAE,MAAM,YAAY,CAAC;AAIhH,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,OAAO,CAAC;IACf,KAAK,EAAE,OAAO,CAAC;IACf,KAAK,EAAE,QAAQ,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,WAAW,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,SAAS,CAAC,EAAE,KAAK,CAAC;IAClB,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,UAAU,CAAC,EAAE,KAAK,CAAC;IACnB,QAAQ,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,eAAe,EAAE,KAAK,CAAA;KAAE,CAAC;IACnE,aAAa,CAAC,EAAE,KAAK,CAAC;CACvB;AAED,4FAA4F;AAC5F,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,kBAAkB,GAAG,cAAc,CA4B5E"}
|
package/dist/mandate.js
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `buildClosedMandate` — construct an unsigned closed (one-shot) PaymentMandate.
|
|
3
|
+
*
|
|
4
|
+
* The wallet + invoice rails (and the demo) build a closed mandate, sign it via
|
|
5
|
+
* `signPaymentMandate`, then settle it with a single transfer. Closed + one-shot per
|
|
6
|
+
* PMT-10 / PMT-INV-14. `orderHash`/`legId` (EXC-R2) bind the leg to an ExchangeOrder.
|
|
7
|
+
*/
|
|
8
|
+
import { computeMandateId } from './index.js';
|
|
9
|
+
const ZERO32 = ('0x' + '00'.repeat(32));
|
|
10
|
+
/** Build the unsigned closed mandate (signature `'0x'`); sign with `signPaymentMandate`. */
|
|
11
|
+
export function buildClosedMandate(input) {
|
|
12
|
+
const validFrom = input.validFrom ?? 0;
|
|
13
|
+
return {
|
|
14
|
+
mandateId: computeMandateId({ payer: input.payer, nonce: input.nonce, rail: input.rail, chain: input.chain }),
|
|
15
|
+
payer: input.payer,
|
|
16
|
+
payee: input.payee,
|
|
17
|
+
granter: input.granter ?? input.payer,
|
|
18
|
+
rail: input.rail,
|
|
19
|
+
amountPolicy: { kind: 'exact', amount: input.amount, asset: input.asset, chain: input.chain },
|
|
20
|
+
nonce: input.nonce,
|
|
21
|
+
maxRedemptions: 1,
|
|
22
|
+
validFrom,
|
|
23
|
+
expiresAt: input.expiresAt,
|
|
24
|
+
contextBinding: {
|
|
25
|
+
...(input.resource ? { resource: input.resource } : {}),
|
|
26
|
+
orderHash: input.orderHash,
|
|
27
|
+
legId: input.legId,
|
|
28
|
+
chain: input.chain,
|
|
29
|
+
asset: input.asset,
|
|
30
|
+
nonce: input.nonce,
|
|
31
|
+
validFrom,
|
|
32
|
+
expiresAt: input.expiresAt,
|
|
33
|
+
},
|
|
34
|
+
delegationRef: input.delegationRef,
|
|
35
|
+
mode: 'closed',
|
|
36
|
+
reasonHash: input.reasonHash ?? ZERO32,
|
|
37
|
+
signature: '0x',
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=mandate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mandate.js","sourceRoot":"","sources":["../src/mandate.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAAE,gBAAgB,EAAoE,MAAM,YAAY,CAAC;AAEhH,MAAM,MAAM,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAU,CAAC;AAoBjD,4FAA4F;AAC5F,MAAM,UAAU,kBAAkB,CAAC,KAAyB;IAC1D,MAAM,SAAS,GAAG,KAAK,CAAC,SAAS,IAAI,CAAC,CAAC;IACvC,OAAO;QACL,SAAS,EAAE,gBAAgB,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC;QAC7G,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,OAAO,EAAE,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,KAAK;QACrC,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,YAAY,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE;QAC7F,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,cAAc,EAAE,CAAC;QACjB,SAAS;QACT,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,cAAc,EAAE;YACd,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACvD,SAAS,EAAE,KAAK,CAAC,SAAS;YAC1B,KAAK,EAAE,KAAK,CAAC,KAAK;YAClB,KAAK,EAAE,KAAK,CAAC,KAAK;YAClB,KAAK,EAAE,KAAK,CAAC,KAAK;YAClB,KAAK,EAAE,KAAK,CAAC,KAAK;YAClB,SAAS;YACT,SAAS,EAAE,KAAK,CAAC,SAAS;SAC3B;QACD,aAAa,EAAE,KAAK,CAAC,aAAa;QAClC,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE,KAAK,CAAC,UAAU,IAAI,MAAM;QACtC,SAAS,EAAE,IAAI;KAChB,CAAC;AACJ,CAAC"}
|
package/dist/ops.d.ts
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Payment ops core (spec 243 §5.5) — the plumbing every mature payment stack needs:
|
|
3
|
+
* an idempotent event model + webhook-style subscribers, reconciliation/payment-detection,
|
|
4
|
+
* and receipt export. In-process for W1 (the app delivers webhooks later). Pure — no I/O.
|
|
5
|
+
*/
|
|
6
|
+
import type { Address } from '@agenticprimitives/types';
|
|
7
|
+
import type { Hex32 } from './index.js';
|
|
8
|
+
export type PaymentEventType = 'payment.created' | 'payment.reserved' | 'payment.settling' | 'payment.settled' | 'payment.failed' | 'payment.refunded' | 'payment.expired' | 'payment.disputed' | 'entitlement.issued' | 'entitlement.consumed';
|
|
9
|
+
export interface PaymentEvent {
|
|
10
|
+
/** dedupe key — re-emitting the same key is a no-op (at-least-once producers, exactly-once consumers) */
|
|
11
|
+
idempotencyKey: string;
|
|
12
|
+
type: PaymentEventType;
|
|
13
|
+
at: number;
|
|
14
|
+
orderHash?: Hex32;
|
|
15
|
+
mandateId?: Hex32;
|
|
16
|
+
data?: Record<string, unknown>;
|
|
17
|
+
}
|
|
18
|
+
export interface PaymentEventLog {
|
|
19
|
+
/** Returns `{ accepted: false }` when `idempotencyKey` was already seen (no re-emit, no re-notify). */
|
|
20
|
+
emit(event: PaymentEvent): {
|
|
21
|
+
accepted: boolean;
|
|
22
|
+
};
|
|
23
|
+
list(): PaymentEvent[];
|
|
24
|
+
byType(type: PaymentEventType): PaymentEvent[];
|
|
25
|
+
byOrder(orderHash: Hex32): PaymentEvent[];
|
|
26
|
+
/** Webhook-style subscriber — invoked once per ACCEPTED event. Returns an unsubscribe fn. */
|
|
27
|
+
subscribe(fn: (event: PaymentEvent) => void): () => void;
|
|
28
|
+
}
|
|
29
|
+
export declare function createPaymentEventLog(): PaymentEventLog;
|
|
30
|
+
export interface ReceiptRow {
|
|
31
|
+
mandateId: Hex32;
|
|
32
|
+
payer: Address;
|
|
33
|
+
payee: Address;
|
|
34
|
+
asset: Address;
|
|
35
|
+
amount: bigint;
|
|
36
|
+
settlementHash: Hex32;
|
|
37
|
+
at: number;
|
|
38
|
+
orderHash?: Hex32;
|
|
39
|
+
/** set on a refund leg — the original charge it reverses */
|
|
40
|
+
refunds?: Hex32;
|
|
41
|
+
}
|
|
42
|
+
export interface ReceiptFilter {
|
|
43
|
+
payer?: Address;
|
|
44
|
+
payee?: Address;
|
|
45
|
+
orderHash?: Hex32;
|
|
46
|
+
asset?: Address;
|
|
47
|
+
}
|
|
48
|
+
export declare function listReceiptsBy(receipts: ReceiptRow[], filter: ReceiptFilter): ReceiptRow[];
|
|
49
|
+
/** Net balance change for `account` across the receipt set (incoming as payee − outgoing as payer). */
|
|
50
|
+
export declare function balanceDelta(receipts: ReceiptRow[], account: Address): bigint;
|
|
51
|
+
/** Payment detection: is `orderHash` paid (optionally to ≥ `expectedAmount`)? From receipts, not logs. */
|
|
52
|
+
export declare function isOrderPaid(receipts: ReceiptRow[], orderHash: Hex32, expectedAmount?: bigint): boolean;
|
|
53
|
+
export declare function exportReceiptsJSON(receipts: ReceiptRow[]): string;
|
|
54
|
+
export declare function exportReceiptsCSV(receipts: ReceiptRow[]): string;
|
|
55
|
+
//# sourceMappingURL=ops.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ops.d.ts","sourceRoot":"","sources":["../src/ops.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAExC,MAAM,MAAM,gBAAgB,GACxB,iBAAiB,GACjB,kBAAkB,GAClB,kBAAkB,GAClB,iBAAiB,GACjB,gBAAgB,GAChB,kBAAkB,GAClB,iBAAiB,GACjB,kBAAkB,GAClB,oBAAoB,GACpB,sBAAsB,CAAC;AAE3B,MAAM,WAAW,YAAY;IAC3B,yGAAyG;IACzG,cAAc,EAAE,MAAM,CAAC;IACvB,IAAI,EAAE,gBAAgB,CAAC;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,CAAC,EAAE,KAAK,CAAC;IAClB,SAAS,CAAC,EAAE,KAAK,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAChC;AAED,MAAM,WAAW,eAAe;IAC9B,uGAAuG;IACvG,IAAI,CAAC,KAAK,EAAE,YAAY,GAAG;QAAE,QAAQ,EAAE,OAAO,CAAA;KAAE,CAAC;IACjD,IAAI,IAAI,YAAY,EAAE,CAAC;IACvB,MAAM,CAAC,IAAI,EAAE,gBAAgB,GAAG,YAAY,EAAE,CAAC;IAC/C,OAAO,CAAC,SAAS,EAAE,KAAK,GAAG,YAAY,EAAE,CAAC;IAC1C,6FAA6F;IAC7F,SAAS,CAAC,EAAE,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;CAC1D;AAED,wBAAgB,qBAAqB,IAAI,eAAe,CAoBvD;AAID,MAAM,WAAW,UAAU;IACzB,SAAS,EAAE,KAAK,CAAC;IACjB,KAAK,EAAE,OAAO,CAAC;IACf,KAAK,EAAE,OAAO,CAAC;IACf,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,KAAK,CAAC;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,CAAC,EAAE,KAAK,CAAC;IAClB,4DAA4D;IAC5D,OAAO,CAAC,EAAE,KAAK,CAAC;CACjB;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,SAAS,CAAC,EAAE,KAAK,CAAC;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAID,wBAAgB,cAAc,CAAC,QAAQ,EAAE,UAAU,EAAE,EAAE,MAAM,EAAE,aAAa,GAAG,UAAU,EAAE,CAQ1F;AAED,uGAAuG;AACvG,wBAAgB,YAAY,CAAC,QAAQ,EAAE,UAAU,EAAE,EAAE,OAAO,EAAE,OAAO,GAAG,MAAM,CAO7E;AAED,0GAA0G;AAC1G,wBAAgB,WAAW,CAAC,QAAQ,EAAE,UAAU,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,cAAc,CAAC,EAAE,MAAM,GAAG,OAAO,CAMtG;AAID,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,UAAU,EAAE,GAAG,MAAM,CAMjE;AAED,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,UAAU,EAAE,GAAG,MAAM,CAMhE"}
|
package/dist/ops.js
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Payment ops core (spec 243 §5.5) — the plumbing every mature payment stack needs:
|
|
3
|
+
* an idempotent event model + webhook-style subscribers, reconciliation/payment-detection,
|
|
4
|
+
* and receipt export. In-process for W1 (the app delivers webhooks later). Pure — no I/O.
|
|
5
|
+
*/
|
|
6
|
+
export function createPaymentEventLog() {
|
|
7
|
+
const events = [];
|
|
8
|
+
const seen = new Set();
|
|
9
|
+
const subs = new Set();
|
|
10
|
+
return {
|
|
11
|
+
emit(event) {
|
|
12
|
+
if (seen.has(event.idempotencyKey))
|
|
13
|
+
return { accepted: false };
|
|
14
|
+
seen.add(event.idempotencyKey);
|
|
15
|
+
events.push(event);
|
|
16
|
+
for (const fn of subs)
|
|
17
|
+
fn(event);
|
|
18
|
+
return { accepted: true };
|
|
19
|
+
},
|
|
20
|
+
list: () => [...events],
|
|
21
|
+
byType: (type) => events.filter((e) => e.type === type),
|
|
22
|
+
byOrder: (orderHash) => events.filter((e) => e.orderHash?.toLowerCase() === orderHash.toLowerCase()),
|
|
23
|
+
subscribe(fn) {
|
|
24
|
+
subs.add(fn);
|
|
25
|
+
return () => subs.delete(fn);
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
const eq = (a, b) => (a && b ? a.toLowerCase() === b.toLowerCase() : a === b);
|
|
30
|
+
export function listReceiptsBy(receipts, filter) {
|
|
31
|
+
return receipts.filter((r) => (filter.payer === undefined || eq(r.payer, filter.payer)) &&
|
|
32
|
+
(filter.payee === undefined || eq(r.payee, filter.payee)) &&
|
|
33
|
+
(filter.asset === undefined || eq(r.asset, filter.asset)) &&
|
|
34
|
+
(filter.orderHash === undefined || eq(r.orderHash, filter.orderHash)));
|
|
35
|
+
}
|
|
36
|
+
/** Net balance change for `account` across the receipt set (incoming as payee − outgoing as payer). */
|
|
37
|
+
export function balanceDelta(receipts, account) {
|
|
38
|
+
let delta = 0n;
|
|
39
|
+
for (const r of receipts) {
|
|
40
|
+
if (eq(r.payee, account))
|
|
41
|
+
delta += r.amount;
|
|
42
|
+
if (eq(r.payer, account))
|
|
43
|
+
delta -= r.amount;
|
|
44
|
+
}
|
|
45
|
+
return delta;
|
|
46
|
+
}
|
|
47
|
+
/** Payment detection: is `orderHash` paid (optionally to ≥ `expectedAmount`)? From receipts, not logs. */
|
|
48
|
+
export function isOrderPaid(receipts, orderHash, expectedAmount) {
|
|
49
|
+
const charges = receipts.filter((r) => eq(r.orderHash, orderHash) && !r.refunds);
|
|
50
|
+
if (charges.length === 0)
|
|
51
|
+
return false;
|
|
52
|
+
if (expectedAmount === undefined)
|
|
53
|
+
return true;
|
|
54
|
+
const total = charges.reduce((s, r) => s + r.amount, 0n);
|
|
55
|
+
return total >= expectedAmount;
|
|
56
|
+
}
|
|
57
|
+
// ── export ──────────────────────────────────────────────────────────
|
|
58
|
+
export function exportReceiptsJSON(receipts) {
|
|
59
|
+
return JSON.stringify(receipts.map((r) => ({ ...r, amount: r.amount.toString() })), null, 2);
|
|
60
|
+
}
|
|
61
|
+
export function exportReceiptsCSV(receipts) {
|
|
62
|
+
const header = 'mandateId,payer,payee,asset,amount,settlementHash,at,orderHash,refunds';
|
|
63
|
+
const rows = receipts.map((r) => [r.mandateId, r.payer, r.payee, r.asset, r.amount.toString(), r.settlementHash, r.at, r.orderHash ?? '', r.refunds ?? ''].join(','));
|
|
64
|
+
return [header, ...rows].join('\n');
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=ops.js.map
|
package/dist/ops.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ops.js","sourceRoot":"","sources":["../src/ops.ts"],"names":[],"mappings":"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"}
|