@heraldprotocol/mpp 0.0.1
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 +116 -0
- package/dist/cjs/client.cjs +242 -0
- package/dist/cjs/client.cjs.map +1 -0
- package/dist/cjs/client.d.cts +112 -0
- package/dist/cjs/index.cjs +71 -0
- package/dist/cjs/index.cjs.map +1 -0
- package/dist/cjs/index.d.cts +54 -0
- package/dist/cjs/server.cjs +397 -0
- package/dist/cjs/server.cjs.map +1 -0
- package/dist/cjs/server.d.cts +84 -0
- package/dist/cjs/types-CKXzdGiJ.d.cts +3 -0
- package/dist/esm/chunk-CRRGQQSN.js +45 -0
- package/dist/esm/chunk-CRRGQQSN.js.map +1 -0
- package/dist/esm/chunk-XBFBAAXJ.js +87 -0
- package/dist/esm/chunk-XBFBAAXJ.js.map +1 -0
- package/dist/esm/client.d.ts +112 -0
- package/dist/esm/client.js +150 -0
- package/dist/esm/client.js.map +1 -0
- package/dist/esm/index.d.ts +54 -0
- package/dist/esm/index.js +7 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/server.d.ts +84 -0
- package/dist/esm/server.js +260 -0
- package/dist/esm/server.js.map +1 -0
- package/dist/esm/types-CKXzdGiJ.d.ts +3 -0
- package/package.json +61 -0
- package/src/Methods.ts +43 -0
- package/src/client/Charge.ts +195 -0
- package/src/client/Methods.ts +29 -0
- package/src/client/index.ts +2 -0
- package/src/defaults.ts +100 -0
- package/src/index.ts +1 -0
- package/src/server/Charge.ts +382 -0
- package/src/server/Methods.ts +29 -0
- package/src/server/index.ts +2 -0
- package/src/types.ts +1 -0
|
@@ -0,0 +1,397 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/server/index.ts
|
|
31
|
+
var server_exports = {};
|
|
32
|
+
__export(server_exports, {
|
|
33
|
+
charge: () => charge2,
|
|
34
|
+
zerog: () => zerog
|
|
35
|
+
});
|
|
36
|
+
module.exports = __toCommonJS(server_exports);
|
|
37
|
+
|
|
38
|
+
// src/server/Charge.ts
|
|
39
|
+
var import_mppx2 = require("mppx");
|
|
40
|
+
var import_viem2 = require("viem");
|
|
41
|
+
var import_accounts = require("viem/accounts");
|
|
42
|
+
var import_actions = require("viem/actions");
|
|
43
|
+
|
|
44
|
+
// src/defaults.ts
|
|
45
|
+
var chainId = {
|
|
46
|
+
mainnet: 16661,
|
|
47
|
+
testnet: 16602
|
|
48
|
+
};
|
|
49
|
+
var USDC_E = "0x1f3aa82227281ca364bfb3d253b0f1af1da6473e";
|
|
50
|
+
var currency = {
|
|
51
|
+
[chainId.mainnet]: USDC_E
|
|
52
|
+
};
|
|
53
|
+
var decimals = 6;
|
|
54
|
+
var rpcUrl = {
|
|
55
|
+
[chainId.mainnet]: "https://evmrpc.0g.ai",
|
|
56
|
+
[chainId.testnet]: "https://evmrpc-testnet.0g.ai"
|
|
57
|
+
};
|
|
58
|
+
var erc3009Abi = [
|
|
59
|
+
{
|
|
60
|
+
type: "function",
|
|
61
|
+
name: "transferWithAuthorization",
|
|
62
|
+
inputs: [
|
|
63
|
+
{ name: "from", type: "address" },
|
|
64
|
+
{ name: "to", type: "address" },
|
|
65
|
+
{ name: "value", type: "uint256" },
|
|
66
|
+
{ name: "validAfter", type: "uint256" },
|
|
67
|
+
{ name: "validBefore", type: "uint256" },
|
|
68
|
+
{ name: "nonce", type: "bytes32" },
|
|
69
|
+
{ name: "v", type: "uint8" },
|
|
70
|
+
{ name: "r", type: "bytes32" },
|
|
71
|
+
{ name: "s", type: "bytes32" }
|
|
72
|
+
],
|
|
73
|
+
outputs: [],
|
|
74
|
+
stateMutability: "nonpayable"
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
type: "function",
|
|
78
|
+
name: "receiveWithAuthorization",
|
|
79
|
+
inputs: [
|
|
80
|
+
{ name: "from", type: "address" },
|
|
81
|
+
{ name: "to", type: "address" },
|
|
82
|
+
{ name: "value", type: "uint256" },
|
|
83
|
+
{ name: "validAfter", type: "uint256" },
|
|
84
|
+
{ name: "validBefore", type: "uint256" },
|
|
85
|
+
{ name: "nonce", type: "bytes32" },
|
|
86
|
+
{ name: "v", type: "uint8" },
|
|
87
|
+
{ name: "r", type: "bytes32" },
|
|
88
|
+
{ name: "s", type: "bytes32" }
|
|
89
|
+
],
|
|
90
|
+
outputs: [],
|
|
91
|
+
stateMutability: "nonpayable"
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
type: "function",
|
|
95
|
+
name: "name",
|
|
96
|
+
inputs: [],
|
|
97
|
+
outputs: [{ name: "", type: "string" }],
|
|
98
|
+
stateMutability: "view"
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
type: "function",
|
|
102
|
+
name: "version",
|
|
103
|
+
inputs: [],
|
|
104
|
+
outputs: [{ name: "", type: "string" }],
|
|
105
|
+
stateMutability: "view"
|
|
106
|
+
}
|
|
107
|
+
];
|
|
108
|
+
var erc3009Tokens = {
|
|
109
|
+
[USDC_E.toLowerCase()]: {
|
|
110
|
+
name: "Bridged USDC",
|
|
111
|
+
version: "2"
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
function resolveCurrency(parameters) {
|
|
115
|
+
const id = parameters.chainId ?? (parameters.testnet ? chainId.testnet : chainId.mainnet);
|
|
116
|
+
const resolved = currency[id];
|
|
117
|
+
if (!resolved)
|
|
118
|
+
throw new Error(`No default currency configured for chainId ${id}.`);
|
|
119
|
+
return resolved;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// src/Methods.ts
|
|
123
|
+
var import_mppx = require("mppx");
|
|
124
|
+
var import_viem = require("viem");
|
|
125
|
+
var charge = import_mppx.Method.from({
|
|
126
|
+
name: "zerog",
|
|
127
|
+
intent: "charge",
|
|
128
|
+
schema: {
|
|
129
|
+
credential: {
|
|
130
|
+
payload: import_mppx.z.discriminatedUnion("type", [
|
|
131
|
+
import_mppx.z.object({ hash: import_mppx.z.hash(), type: import_mppx.z.literal("hash") }),
|
|
132
|
+
import_mppx.z.object({
|
|
133
|
+
type: import_mppx.z.literal("authorization"),
|
|
134
|
+
from: import_mppx.z.string(),
|
|
135
|
+
to: import_mppx.z.string(),
|
|
136
|
+
value: import_mppx.z.string(),
|
|
137
|
+
validAfter: import_mppx.z.string(),
|
|
138
|
+
validBefore: import_mppx.z.string(),
|
|
139
|
+
nonce: import_mppx.z.string(),
|
|
140
|
+
signature: import_mppx.z.string()
|
|
141
|
+
})
|
|
142
|
+
])
|
|
143
|
+
},
|
|
144
|
+
request: import_mppx.z.pipe(
|
|
145
|
+
import_mppx.z.object({
|
|
146
|
+
amount: import_mppx.z.amount(),
|
|
147
|
+
chainId: import_mppx.z.optional(import_mppx.z.number()),
|
|
148
|
+
currency: import_mppx.z.string(),
|
|
149
|
+
decimals: import_mppx.z.number(),
|
|
150
|
+
description: import_mppx.z.optional(import_mppx.z.string()),
|
|
151
|
+
externalId: import_mppx.z.optional(import_mppx.z.string()),
|
|
152
|
+
recipient: import_mppx.z.optional(import_mppx.z.string())
|
|
153
|
+
}),
|
|
154
|
+
import_mppx.z.transform(({ amount, chainId: chainId2, decimals: decimals2, ...rest }) => ({
|
|
155
|
+
...rest,
|
|
156
|
+
amount: (0, import_viem.parseUnits)(amount, decimals2).toString(),
|
|
157
|
+
...chainId2 !== void 0 ? { methodDetails: { chainId: chainId2 } } : {}
|
|
158
|
+
}))
|
|
159
|
+
)
|
|
160
|
+
}
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
// src/server/Charge.ts
|
|
164
|
+
function charge2(parameters = {}) {
|
|
165
|
+
const {
|
|
166
|
+
amount,
|
|
167
|
+
currency: currency2 = resolveCurrency(parameters),
|
|
168
|
+
decimals: decimals2 = decimals,
|
|
169
|
+
description,
|
|
170
|
+
externalId,
|
|
171
|
+
recipient,
|
|
172
|
+
waitForConfirmation = true
|
|
173
|
+
} = parameters;
|
|
174
|
+
const store = parameters.store ?? import_mppx2.Store.memory();
|
|
175
|
+
if (currency2.toLowerCase() in erc3009Tokens && !parameters.account) {
|
|
176
|
+
throw new Error(
|
|
177
|
+
"ERC-3009 requires an `account` parameter so the server can sign and broadcast the transferWithAuthorization transaction."
|
|
178
|
+
);
|
|
179
|
+
}
|
|
180
|
+
const serverAccount = parameters.account ? typeof parameters.account === "string" ? (0, import_accounts.parseAccount)(parameters.account) : parameters.account : void 0;
|
|
181
|
+
const resolveClient = async (chainId2) => {
|
|
182
|
+
if (parameters.getClient) return parameters.getClient({ chainId: chainId2 });
|
|
183
|
+
const id = chainId2 ?? chainId.mainnet;
|
|
184
|
+
const url = rpcUrl[id];
|
|
185
|
+
if (!url) throw new Error(`No RPC URL configured for chainId ${id}.`);
|
|
186
|
+
const { createClient, http } = await import("viem");
|
|
187
|
+
return createClient({ chain: { id }, transport: http(url) });
|
|
188
|
+
};
|
|
189
|
+
return import_mppx2.Method.toServer(charge, {
|
|
190
|
+
defaults: {
|
|
191
|
+
amount,
|
|
192
|
+
currency: currency2,
|
|
193
|
+
decimals: decimals2,
|
|
194
|
+
description,
|
|
195
|
+
externalId,
|
|
196
|
+
recipient
|
|
197
|
+
},
|
|
198
|
+
async request({ request }) {
|
|
199
|
+
const chainId2 = await (async () => {
|
|
200
|
+
if (request.chainId) return request.chainId;
|
|
201
|
+
if (parameters.testnet) return chainId.testnet;
|
|
202
|
+
return (await resolveClient(void 0)).chain?.id;
|
|
203
|
+
})();
|
|
204
|
+
const client = await (async () => {
|
|
205
|
+
try {
|
|
206
|
+
return await resolveClient(chainId2);
|
|
207
|
+
} catch {
|
|
208
|
+
throw new Error(`No client configured with chainId ${chainId2}.`);
|
|
209
|
+
}
|
|
210
|
+
})();
|
|
211
|
+
if (client.chain?.id !== chainId2)
|
|
212
|
+
throw new Error(`Client not configured with chainId ${chainId2}.`);
|
|
213
|
+
return { ...request, chainId: chainId2 };
|
|
214
|
+
},
|
|
215
|
+
async verify({ credential, request }) {
|
|
216
|
+
const { challenge } = credential;
|
|
217
|
+
const { chainId: chainId2 } = request;
|
|
218
|
+
const client = await resolveClient(chainId2);
|
|
219
|
+
const { request: challengeRequest } = challenge;
|
|
220
|
+
const challengeAmount = challengeRequest.amount;
|
|
221
|
+
const challengeCurrency = challengeRequest.currency;
|
|
222
|
+
const challengeRecipient = challengeRequest.recipient;
|
|
223
|
+
const expires = challenge.expires;
|
|
224
|
+
if (expires && new Date(expires) < /* @__PURE__ */ new Date()) {
|
|
225
|
+
throw new Error(`Payment expired at ${expires}.`);
|
|
226
|
+
}
|
|
227
|
+
const payload = credential.payload;
|
|
228
|
+
switch (payload.type) {
|
|
229
|
+
case "hash": {
|
|
230
|
+
const hash = payload.hash;
|
|
231
|
+
await assertHashUnused(store, hash);
|
|
232
|
+
const sender = extractDidAddress(credential.source);
|
|
233
|
+
if (!sender)
|
|
234
|
+
throw new Error(
|
|
235
|
+
"Hash credential is missing a valid `source` DID \u2014 cannot verify sender."
|
|
236
|
+
);
|
|
237
|
+
const receipt = await (0, import_actions.getTransactionReceipt)(client, { hash });
|
|
238
|
+
const transferLogs = (0, import_viem2.parseEventLogs)({
|
|
239
|
+
abi: import_viem2.erc20Abi,
|
|
240
|
+
eventName: "Transfer",
|
|
241
|
+
logs: receipt.logs
|
|
242
|
+
});
|
|
243
|
+
const match = transferLogs.find(
|
|
244
|
+
(log) => (0, import_viem2.isAddressEqual)(log.address, challengeCurrency) && (0, import_viem2.isAddressEqual)(log.args.from, sender) && (0, import_viem2.isAddressEqual)(log.args.to, challengeRecipient) && log.args.value.toString() === challengeAmount
|
|
245
|
+
);
|
|
246
|
+
if (!match)
|
|
247
|
+
throw new MismatchError(
|
|
248
|
+
"Payment verification failed: no matching ERC-20 transfer found.",
|
|
249
|
+
{
|
|
250
|
+
sender,
|
|
251
|
+
amount: challengeAmount,
|
|
252
|
+
currency: challengeCurrency,
|
|
253
|
+
recipient: challengeRecipient
|
|
254
|
+
}
|
|
255
|
+
);
|
|
256
|
+
await markHashUsed(store, hash);
|
|
257
|
+
return toReceipt(receipt);
|
|
258
|
+
}
|
|
259
|
+
case "authorization": {
|
|
260
|
+
if (!serverAccount) {
|
|
261
|
+
throw new Error(
|
|
262
|
+
"Received ERC-3009 authorization credential but no server `account` is configured. Set `account` in charge parameters to broadcast transferWithAuthorization."
|
|
263
|
+
);
|
|
264
|
+
}
|
|
265
|
+
const { from, to, value, validAfter, validBefore, nonce, signature } = payload;
|
|
266
|
+
const r = `0x${signature.slice(2, 66)}`;
|
|
267
|
+
const s = `0x${signature.slice(66, 130)}`;
|
|
268
|
+
const v = parseInt(signature.slice(130, 132), 16);
|
|
269
|
+
if (!(0, import_viem2.isAddressEqual)(to, challengeRecipient))
|
|
270
|
+
throw new MismatchError(
|
|
271
|
+
"Authorization recipient does not match challenge.",
|
|
272
|
+
{ expected: challengeRecipient, actual: to }
|
|
273
|
+
);
|
|
274
|
+
if (value !== challengeAmount)
|
|
275
|
+
throw new MismatchError(
|
|
276
|
+
"Authorization amount does not match challenge.",
|
|
277
|
+
{ expected: challengeAmount, actual: value }
|
|
278
|
+
);
|
|
279
|
+
const validBeforeTs = Number(validBefore);
|
|
280
|
+
if (validBeforeTs > 0 && validBeforeTs < Math.floor(Date.now() / 1e3)) {
|
|
281
|
+
throw new Error(
|
|
282
|
+
`ERC-3009 authorization expired (validBefore: ${validBefore}).`
|
|
283
|
+
);
|
|
284
|
+
}
|
|
285
|
+
const hash = (0, import_viem2.keccak256)(signature);
|
|
286
|
+
await assertHashUnused(store, hash);
|
|
287
|
+
await markHashUsed(store, hash);
|
|
288
|
+
if (waitForConfirmation) {
|
|
289
|
+
const receipt = await (0, import_actions.sendTransactionSync)(client, {
|
|
290
|
+
account: serverAccount,
|
|
291
|
+
chain: client.chain,
|
|
292
|
+
to: challengeCurrency,
|
|
293
|
+
data: (0, import_viem2.encodeFunctionData)({
|
|
294
|
+
abi: erc3009Abi,
|
|
295
|
+
functionName: "transferWithAuthorization",
|
|
296
|
+
args: [
|
|
297
|
+
from,
|
|
298
|
+
to,
|
|
299
|
+
BigInt(value),
|
|
300
|
+
BigInt(validAfter),
|
|
301
|
+
BigInt(validBefore),
|
|
302
|
+
nonce,
|
|
303
|
+
v,
|
|
304
|
+
r,
|
|
305
|
+
s
|
|
306
|
+
]
|
|
307
|
+
})
|
|
308
|
+
});
|
|
309
|
+
return toReceipt(receipt);
|
|
310
|
+
}
|
|
311
|
+
const txHash = await (0, import_actions.sendTransaction)(client, {
|
|
312
|
+
account: serverAccount,
|
|
313
|
+
chain: client.chain,
|
|
314
|
+
to: challengeCurrency,
|
|
315
|
+
data: (0, import_viem2.encodeFunctionData)({
|
|
316
|
+
abi: erc3009Abi,
|
|
317
|
+
functionName: "transferWithAuthorization",
|
|
318
|
+
args: [
|
|
319
|
+
from,
|
|
320
|
+
to,
|
|
321
|
+
BigInt(value),
|
|
322
|
+
BigInt(validAfter),
|
|
323
|
+
BigInt(validBefore),
|
|
324
|
+
nonce,
|
|
325
|
+
v,
|
|
326
|
+
r,
|
|
327
|
+
s
|
|
328
|
+
]
|
|
329
|
+
})
|
|
330
|
+
});
|
|
331
|
+
return {
|
|
332
|
+
method: "zerog",
|
|
333
|
+
status: "success",
|
|
334
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
335
|
+
reference: txHash
|
|
336
|
+
};
|
|
337
|
+
}
|
|
338
|
+
default:
|
|
339
|
+
throw new Error(
|
|
340
|
+
`Unsupported credential type "${payload.type}".`
|
|
341
|
+
);
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
});
|
|
345
|
+
}
|
|
346
|
+
function getHashStoreKey(hash) {
|
|
347
|
+
return `mppx:charge:${hash.toLowerCase()}`;
|
|
348
|
+
}
|
|
349
|
+
async function assertHashUnused(store, hash) {
|
|
350
|
+
const seen = await store.get(getHashStoreKey(hash));
|
|
351
|
+
if (seen !== null) throw new Error("Transaction hash has already been used.");
|
|
352
|
+
}
|
|
353
|
+
async function markHashUsed(store, hash) {
|
|
354
|
+
await store.put(getHashStoreKey(hash), Date.now());
|
|
355
|
+
}
|
|
356
|
+
function toReceipt(receipt) {
|
|
357
|
+
const { status, transactionHash } = receipt;
|
|
358
|
+
if (status !== "success") {
|
|
359
|
+
throw new Error(`Transaction reverted: ${transactionHash}`);
|
|
360
|
+
}
|
|
361
|
+
return {
|
|
362
|
+
method: "zerog",
|
|
363
|
+
status: "success",
|
|
364
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
365
|
+
reference: transactionHash
|
|
366
|
+
};
|
|
367
|
+
}
|
|
368
|
+
function extractDidAddress(source) {
|
|
369
|
+
if (!source) return void 0;
|
|
370
|
+
const match = /^did:pkh:eip155:\d+:(0x[0-9a-fA-F]{40})$/.exec(source);
|
|
371
|
+
return match ? match[1] : void 0;
|
|
372
|
+
}
|
|
373
|
+
var MismatchError = class extends Error {
|
|
374
|
+
constructor(reason, details) {
|
|
375
|
+
super(
|
|
376
|
+
[
|
|
377
|
+
reason,
|
|
378
|
+
...Object.entries(details).map(([k, v]) => ` - ${k}: ${v}`)
|
|
379
|
+
].join("\n")
|
|
380
|
+
);
|
|
381
|
+
this.name = "MismatchError";
|
|
382
|
+
}
|
|
383
|
+
};
|
|
384
|
+
|
|
385
|
+
// src/server/Methods.ts
|
|
386
|
+
function zerog(parameters) {
|
|
387
|
+
return [zerog.charge(parameters)];
|
|
388
|
+
}
|
|
389
|
+
((zerog2) => {
|
|
390
|
+
zerog2.charge = charge2;
|
|
391
|
+
})(zerog || (zerog = {}));
|
|
392
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
393
|
+
0 && (module.exports = {
|
|
394
|
+
charge,
|
|
395
|
+
zerog
|
|
396
|
+
});
|
|
397
|
+
//# sourceMappingURL=server.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/server/index.ts","../../src/server/Charge.ts","../../src/defaults.ts","../../src/Methods.ts","../../src/server/Methods.ts"],"sourcesContent":["export { charge } from \"./Charge.js\";\nexport { zerog } from \"./Methods.js\";\n","import type { Account, Address, Chain, Client, TransactionReceipt } from \"viem\";\nimport { Method, Store } from \"mppx\";\nimport {\n encodeFunctionData,\n erc20Abi,\n isAddressEqual,\n keccak256,\n parseEventLogs,\n} from \"viem\";\nimport { parseAccount } from \"viem/accounts\";\nimport {\n getTransactionReceipt,\n sendTransaction,\n sendTransactionSync,\n} from \"viem/actions\";\n\nimport type { MaybePromise } from \"../types.js\";\nimport * as defaults from \"../defaults.js\";\nimport * as Methods from \"../Methods.js\";\n\n/**\n * Creates a 0G charge method intent for usage on the server.\n *\n * @example\n * ```ts\n * import { zerog } from \"@heraldprotocol/mpp/server\";\n *\n * const charge = zerog.charge({\n * recipient: \"0x...\",\n * currency: \"0x...\",\n * account: privateKeyToAccount(\"0x...\"),\n * });\n * ```\n */\nexport function charge(parameters: charge.Parameters = {}): Method.AnyServer {\n const {\n amount,\n currency = defaults.resolveCurrency(parameters),\n decimals = defaults.decimals,\n description,\n externalId,\n recipient,\n waitForConfirmation = true,\n } = parameters;\n const store = (parameters.store ??\n Store.memory()) as Store.Store<charge.StoreItemMap>;\n\n if (currency.toLowerCase() in defaults.erc3009Tokens && !parameters.account) {\n throw new Error(\n \"ERC-3009 requires an `account` parameter so the server can sign and broadcast \" +\n \"the transferWithAuthorization transaction.\"\n );\n }\n\n const serverAccount = parameters.account\n ? typeof parameters.account === \"string\"\n ? parseAccount(parameters.account)\n : parameters.account\n : undefined;\n\n const resolveClient = async (\n chainId?: number | undefined\n ): Promise<Client> => {\n if (parameters.getClient) return parameters.getClient({ chainId });\n const id = chainId ?? defaults.chainId.mainnet;\n const url = defaults.rpcUrl[id];\n if (!url) throw new Error(`No RPC URL configured for chainId ${id}.`);\n const { createClient, http } = await import(\"viem\");\n return createClient({ chain: { id } as Chain, transport: http(url) });\n };\n\n return Method.toServer(Methods.charge, {\n defaults: {\n amount,\n currency,\n decimals,\n description,\n externalId,\n recipient,\n } as never,\n\n async request({ request }) {\n const chainId = await (async () => {\n if (request.chainId) return request.chainId;\n if (parameters.testnet) return defaults.chainId.testnet;\n return (await resolveClient(undefined)).chain?.id;\n })();\n\n const client = await (async () => {\n try {\n return await resolveClient(chainId);\n } catch {\n throw new Error(`No client configured with chainId ${chainId}.`);\n }\n })();\n if (client.chain?.id !== chainId)\n throw new Error(`Client not configured with chainId ${chainId}.`);\n\n return { ...request, chainId };\n },\n\n async verify({ credential, request }) {\n const { challenge } = credential;\n const { chainId } = request;\n\n const client = await resolveClient(chainId);\n\n const { request: challengeRequest } = challenge;\n const challengeAmount = challengeRequest.amount as string;\n const challengeCurrency = challengeRequest.currency as Address;\n const challengeRecipient = challengeRequest.recipient as Address;\n const expires = challenge.expires;\n\n if (expires && new Date(expires) < new Date()) {\n throw new Error(`Payment expired at ${expires}.`);\n }\n\n const payload = credential.payload;\n\n switch (payload.type) {\n case \"hash\": {\n const hash = payload.hash as `0x${string}`;\n await assertHashUnused(store, hash);\n\n const sender = extractDidAddress(credential.source);\n if (!sender)\n throw new Error(\n \"Hash credential is missing a valid `source` DID — cannot verify sender.\"\n );\n\n const receipt = await getTransactionReceipt(client, { hash });\n\n const transferLogs = parseEventLogs({\n abi: erc20Abi,\n eventName: \"Transfer\",\n logs: receipt.logs,\n });\n\n const match = transferLogs.find(\n (log) =>\n isAddressEqual(log.address, challengeCurrency) &&\n isAddressEqual(log.args.from, sender) &&\n isAddressEqual(log.args.to, challengeRecipient) &&\n log.args.value.toString() === challengeAmount\n );\n\n if (!match)\n throw new MismatchError(\n \"Payment verification failed: no matching ERC-20 transfer found.\",\n {\n sender,\n amount: challengeAmount,\n currency: challengeCurrency,\n recipient: challengeRecipient,\n }\n );\n\n await markHashUsed(store, hash);\n\n return toReceipt(receipt);\n }\n\n case \"authorization\": {\n if (!serverAccount) {\n throw new Error(\n \"Received ERC-3009 authorization credential but no server `account` is configured. \" +\n \"Set `account` in charge parameters to broadcast transferWithAuthorization.\"\n );\n }\n\n const { from, to, value, validAfter, validBefore, nonce, signature } =\n payload as {\n from: string;\n to: string;\n value: string;\n validAfter: string;\n validBefore: string;\n nonce: string;\n signature: string;\n };\n\n // Split signature into v, r, s for the contract call\n const r = `0x${signature.slice(2, 66)}` as `0x${string}`;\n const s = `0x${signature.slice(66, 130)}` as `0x${string}`;\n const v = parseInt(signature.slice(130, 132), 16);\n\n // Validate authorization parameters match the challenge\n if (!isAddressEqual(to as Address, challengeRecipient))\n throw new MismatchError(\n \"Authorization recipient does not match challenge.\",\n { expected: challengeRecipient, actual: to }\n );\n\n if (value !== challengeAmount)\n throw new MismatchError(\n \"Authorization amount does not match challenge.\",\n { expected: challengeAmount, actual: value }\n );\n\n // Check expiry from the authorization itself\n const validBeforeTs = Number(validBefore);\n if (\n validBeforeTs > 0 &&\n validBeforeTs < Math.floor(Date.now() / 1000)\n ) {\n throw new Error(\n `ERC-3009 authorization expired (validBefore: ${validBefore}).`\n );\n }\n\n const hash = keccak256(signature as `0x${string}`);\n await assertHashUnused(store, hash);\n await markHashUsed(store, hash);\n\n if (waitForConfirmation) {\n const receipt = await sendTransactionSync(client, {\n account: serverAccount,\n chain: client.chain,\n to: challengeCurrency,\n data: encodeFunctionData({\n abi: defaults.erc3009Abi,\n functionName: \"transferWithAuthorization\",\n args: [\n from as Address,\n to as Address,\n BigInt(value),\n BigInt(validAfter),\n BigInt(validBefore),\n nonce as `0x${string}`,\n v,\n r as `0x${string}`,\n s as `0x${string}`,\n ],\n }),\n } as never);\n\n return toReceipt(receipt);\n }\n\n const txHash = await sendTransaction(client, {\n account: serverAccount,\n chain: client.chain,\n to: challengeCurrency,\n data: encodeFunctionData({\n abi: defaults.erc3009Abi,\n functionName: \"transferWithAuthorization\",\n args: [\n from as Address,\n to as Address,\n BigInt(value),\n BigInt(validAfter),\n BigInt(validBefore),\n nonce as `0x${string}`,\n v,\n r as `0x${string}`,\n s as `0x${string}`,\n ],\n }),\n } as never);\n\n return {\n method: \"zerog\" as const,\n status: \"success\" as const,\n timestamp: new Date().toISOString(),\n reference: txHash,\n };\n }\n\n default:\n throw new Error(\n `Unsupported credential type \"${(payload as { type: string }).type}\".`\n );\n }\n },\n });\n}\n\nexport declare namespace charge {\n type StoreItemMap = {\n [key: `mppx:charge:${string}`]: number;\n };\n\n type Parameters = {\n /** Default payment amount (human-readable, e.g. \"1.50\"). */\n amount?: string | undefined;\n /** ERC-20 token contract address. */\n currency?: string | undefined;\n /** Token decimals. @default 6 */\n decimals?: number | undefined;\n /** Human-readable description. */\n description?: string | undefined;\n /** External identifier to echo back in receipt. */\n externalId?: string | undefined;\n /** Recipient address for payments. */\n recipient?: string | undefined;\n /** Testnet mode. */\n testnet?: boolean | undefined;\n /**\n * Whether to wait for the charge transaction to confirm on-chain.\n * @default true\n */\n waitForConfirmation?: boolean | undefined;\n /** Function that returns a viem Client for the given chain ID. */\n getClient?:\n | ((parameters: { chainId?: number | undefined }) => MaybePromise<Client>)\n | undefined;\n /**\n * Server account used to broadcast `transferWithAuthorization` transactions.\n * Required when accepting `authorization` payloads. The server pays gas\n * from this account.\n */\n account?: Account | Address | undefined;\n /**\n * Store for transaction hash replay protection.\n *\n * Use a shared store in multi-instance deployments so consumed hashes are\n * visible across all server instances.\n */\n store?: Store.Store | undefined;\n };\n}\n\n/** @internal */\nfunction getHashStoreKey(hash: `0x${string}`): `mppx:charge:${string}` {\n return `mppx:charge:${hash.toLowerCase()}`;\n}\n\n/** @internal */\nasync function assertHashUnused(\n store: Store.Store<charge.StoreItemMap>,\n hash: `0x${string}`\n): Promise<void> {\n const seen = await store.get(getHashStoreKey(hash));\n if (seen !== null) throw new Error(\"Transaction hash has already been used.\");\n}\n\n/** @internal */\nasync function markHashUsed(\n store: Store.Store<charge.StoreItemMap>,\n hash: `0x${string}`\n): Promise<void> {\n await store.put(getHashStoreKey(hash), Date.now());\n}\n\n/** @internal */\nfunction toReceipt(receipt: TransactionReceipt) {\n const { status, transactionHash } = receipt;\n if (status !== \"success\") {\n throw new Error(`Transaction reverted: ${transactionHash}`);\n }\n return {\n method: \"zerog\" as const,\n status: \"success\" as const,\n timestamp: new Date().toISOString(),\n reference: transactionHash,\n };\n}\n\n/**\n * Extracts an Ethereum address from a `did:pkh:eip155:<chainId>:<address>` DID.\n * Returns `undefined` if the source is missing or malformed.\n * @internal\n */\nfunction extractDidAddress(source: string | undefined): Address | undefined {\n if (!source) return undefined;\n const match = /^did:pkh:eip155:\\d+:(0x[0-9a-fA-F]{40})$/.exec(source);\n return match ? (match[1] as Address) : undefined;\n}\n\n/** @internal */\nclass MismatchError extends Error {\n override readonly name = \"MismatchError\";\n\n constructor(reason: string, details: Record<string, string>) {\n super(\n [\n reason,\n ...Object.entries(details).map(([k, v]) => ` - ${k}: ${v}`),\n ].join(\"\\n\")\n );\n }\n}\n","export const chainId = {\n mainnet: 16661,\n testnet: 16602,\n} as const;\n\nexport type ChainId = (typeof chainId)[keyof typeof chainId];\n\nconst USDC_E = \"0x1f3aa82227281ca364bfb3d253b0f1af1da6473e\";\n\n/** Chain ID → default currency. */\nexport const currency: Partial<Record<ChainId, string>> = {\n [chainId.mainnet]: USDC_E,\n};\n\n/** Default token decimals for USDC.e. */\nexport const decimals = 6;\n\n/** Default RPC URLs per chain. */\nexport const rpcUrl: Record<number, string> = {\n [chainId.mainnet]: \"https://evmrpc.0g.ai\",\n [chainId.testnet]: \"https://evmrpc-testnet.0g.ai\",\n};\n\n/** ERC-3009 ABI (`transferWithAuthorization`, `receiveWithAuthorization`). */\nexport const erc3009Abi = [\n {\n type: \"function\",\n name: \"transferWithAuthorization\",\n inputs: [\n { name: \"from\", type: \"address\" },\n { name: \"to\", type: \"address\" },\n { name: \"value\", type: \"uint256\" },\n { name: \"validAfter\", type: \"uint256\" },\n { name: \"validBefore\", type: \"uint256\" },\n { name: \"nonce\", type: \"bytes32\" },\n { name: \"v\", type: \"uint8\" },\n { name: \"r\", type: \"bytes32\" },\n { name: \"s\", type: \"bytes32\" },\n ],\n outputs: [],\n stateMutability: \"nonpayable\",\n },\n {\n type: \"function\",\n name: \"receiveWithAuthorization\",\n inputs: [\n { name: \"from\", type: \"address\" },\n { name: \"to\", type: \"address\" },\n { name: \"value\", type: \"uint256\" },\n { name: \"validAfter\", type: \"uint256\" },\n { name: \"validBefore\", type: \"uint256\" },\n { name: \"nonce\", type: \"bytes32\" },\n { name: \"v\", type: \"uint8\" },\n { name: \"r\", type: \"bytes32\" },\n { name: \"s\", type: \"bytes32\" },\n ],\n outputs: [],\n stateMutability: \"nonpayable\",\n },\n {\n type: \"function\",\n name: \"name\",\n inputs: [],\n outputs: [{ name: \"\", type: \"string\" }],\n stateMutability: \"view\",\n },\n {\n type: \"function\",\n name: \"version\",\n inputs: [],\n outputs: [{ name: \"\", type: \"string\" }],\n stateMutability: \"view\",\n },\n] as const;\n\n/**\n * Known tokens that support ERC-3009 (TransferWithAuthorization).\n * Keyed by lowercase address for case-insensitive lookup.\n */\nexport const erc3009Tokens: Record<string, { name: string; version: string }> =\n {\n [USDC_E.toLowerCase()]: {\n name: \"Bridged USDC\",\n version: \"2\",\n },\n };\n\n/** Resolves the default currency for a given chain. */\nexport function resolveCurrency(parameters: {\n chainId?: number | undefined;\n testnet?: boolean | undefined;\n}): string {\n const id =\n parameters.chainId ??\n (parameters.testnet ? chainId.testnet : chainId.mainnet);\n const resolved = currency[id as ChainId];\n if (!resolved)\n throw new Error(`No default currency configured for chainId ${id}.`);\n return resolved;\n}\n","import { Method, z } from \"mppx\";\nimport { parseUnits } from \"viem\";\n\n/**\n * 0G charge intent for one-time ERC-20 token transfers.\n */\nexport const charge = Method.from({\n name: \"zerog\",\n intent: \"charge\",\n schema: {\n credential: {\n payload: z.discriminatedUnion(\"type\", [\n z.object({ hash: z.hash(), type: z.literal(\"hash\") }),\n z.object({\n type: z.literal(\"authorization\"),\n from: z.string(),\n to: z.string(),\n value: z.string(),\n validAfter: z.string(),\n validBefore: z.string(),\n nonce: z.string(),\n signature: z.string(),\n }),\n ]),\n },\n request: z.pipe(\n z.object({\n amount: z.amount(),\n chainId: z.optional(z.number()),\n currency: z.string(),\n decimals: z.number(),\n description: z.optional(z.string()),\n externalId: z.optional(z.string()),\n recipient: z.optional(z.string()),\n }),\n z.transform(({ amount, chainId, decimals, ...rest }) => ({\n ...rest,\n amount: parseUnits(amount, decimals).toString(),\n ...(chainId !== undefined ? { methodDetails: { chainId } } : {}),\n }))\n ),\n },\n});\n","import type { Method } from \"mppx\";\n\nimport { charge as charge_ } from \"./Charge.js\";\n\n/**\n * Creates a 0G `charge` server method.\n *\n * @example\n * ```ts\n * import { Mppx } from \"mppx/server\";\n * import { zerog } from \"@heraldprotocol/mpp/server\";\n *\n * const mppx = Mppx.create({\n * methods: [zerog({ recipient: \"0x...\", currency: \"0x...\" })],\n * });\n * ```\n */\nexport function zerog(\n parameters?: zerog.Parameters\n): readonly [Method.AnyServer] {\n return [zerog.charge(parameters)] as const;\n}\n\nexport namespace zerog {\n export type Parameters = charge_.Parameters;\n\n /** Creates a 0G `charge` method for one-time ERC-20 token transfers. */\n export const charge = charge_;\n}\n"],"mappings":"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","names":["charge","import_mppx","import_viem","chainId","decimals","charge","currency","decimals","chainId","zerog","charge"]}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { Client, Account, Address } from 'viem';
|
|
2
|
+
import { Method, Store } from 'mppx';
|
|
3
|
+
import { M as MaybePromise } from './types-CKXzdGiJ.cjs';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Creates a 0G charge method intent for usage on the server.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```ts
|
|
10
|
+
* import { zerog } from "@heraldprotocol/mpp/server";
|
|
11
|
+
*
|
|
12
|
+
* const charge = zerog.charge({
|
|
13
|
+
* recipient: "0x...",
|
|
14
|
+
* currency: "0x...",
|
|
15
|
+
* account: privateKeyToAccount("0x..."),
|
|
16
|
+
* });
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
declare function charge(parameters?: charge.Parameters): Method.AnyServer;
|
|
20
|
+
declare namespace charge {
|
|
21
|
+
type StoreItemMap = {
|
|
22
|
+
[key: `mppx:charge:${string}`]: number;
|
|
23
|
+
};
|
|
24
|
+
type Parameters = {
|
|
25
|
+
/** Default payment amount (human-readable, e.g. "1.50"). */
|
|
26
|
+
amount?: string | undefined;
|
|
27
|
+
/** ERC-20 token contract address. */
|
|
28
|
+
currency?: string | undefined;
|
|
29
|
+
/** Token decimals. @default 6 */
|
|
30
|
+
decimals?: number | undefined;
|
|
31
|
+
/** Human-readable description. */
|
|
32
|
+
description?: string | undefined;
|
|
33
|
+
/** External identifier to echo back in receipt. */
|
|
34
|
+
externalId?: string | undefined;
|
|
35
|
+
/** Recipient address for payments. */
|
|
36
|
+
recipient?: string | undefined;
|
|
37
|
+
/** Testnet mode. */
|
|
38
|
+
testnet?: boolean | undefined;
|
|
39
|
+
/**
|
|
40
|
+
* Whether to wait for the charge transaction to confirm on-chain.
|
|
41
|
+
* @default true
|
|
42
|
+
*/
|
|
43
|
+
waitForConfirmation?: boolean | undefined;
|
|
44
|
+
/** Function that returns a viem Client for the given chain ID. */
|
|
45
|
+
getClient?: ((parameters: {
|
|
46
|
+
chainId?: number | undefined;
|
|
47
|
+
}) => MaybePromise<Client>) | undefined;
|
|
48
|
+
/**
|
|
49
|
+
* Server account used to broadcast `transferWithAuthorization` transactions.
|
|
50
|
+
* Required when accepting `authorization` payloads. The server pays gas
|
|
51
|
+
* from this account.
|
|
52
|
+
*/
|
|
53
|
+
account?: Account | Address | undefined;
|
|
54
|
+
/**
|
|
55
|
+
* Store for transaction hash replay protection.
|
|
56
|
+
*
|
|
57
|
+
* Use a shared store in multi-instance deployments so consumed hashes are
|
|
58
|
+
* visible across all server instances.
|
|
59
|
+
*/
|
|
60
|
+
store?: Store.Store | undefined;
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Creates a 0G `charge` server method.
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* ```ts
|
|
69
|
+
* import { Mppx } from "mppx/server";
|
|
70
|
+
* import { zerog } from "@heraldprotocol/mpp/server";
|
|
71
|
+
*
|
|
72
|
+
* const mppx = Mppx.create({
|
|
73
|
+
* methods: [zerog({ recipient: "0x...", currency: "0x..." })],
|
|
74
|
+
* });
|
|
75
|
+
* ```
|
|
76
|
+
*/
|
|
77
|
+
declare function zerog(parameters?: zerog.Parameters): readonly [Method.AnyServer];
|
|
78
|
+
declare namespace zerog {
|
|
79
|
+
type Parameters = charge.Parameters;
|
|
80
|
+
/** Creates a 0G `charge` method for one-time ERC-20 token transfers. */
|
|
81
|
+
const charge: typeof charge;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export { charge, zerog };
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
// src/Methods.ts
|
|
2
|
+
import { Method, z } from "mppx";
|
|
3
|
+
import { parseUnits } from "viem";
|
|
4
|
+
var charge = Method.from({
|
|
5
|
+
name: "zerog",
|
|
6
|
+
intent: "charge",
|
|
7
|
+
schema: {
|
|
8
|
+
credential: {
|
|
9
|
+
payload: z.discriminatedUnion("type", [
|
|
10
|
+
z.object({ hash: z.hash(), type: z.literal("hash") }),
|
|
11
|
+
z.object({
|
|
12
|
+
type: z.literal("authorization"),
|
|
13
|
+
from: z.string(),
|
|
14
|
+
to: z.string(),
|
|
15
|
+
value: z.string(),
|
|
16
|
+
validAfter: z.string(),
|
|
17
|
+
validBefore: z.string(),
|
|
18
|
+
nonce: z.string(),
|
|
19
|
+
signature: z.string()
|
|
20
|
+
})
|
|
21
|
+
])
|
|
22
|
+
},
|
|
23
|
+
request: z.pipe(
|
|
24
|
+
z.object({
|
|
25
|
+
amount: z.amount(),
|
|
26
|
+
chainId: z.optional(z.number()),
|
|
27
|
+
currency: z.string(),
|
|
28
|
+
decimals: z.number(),
|
|
29
|
+
description: z.optional(z.string()),
|
|
30
|
+
externalId: z.optional(z.string()),
|
|
31
|
+
recipient: z.optional(z.string())
|
|
32
|
+
}),
|
|
33
|
+
z.transform(({ amount, chainId, decimals, ...rest }) => ({
|
|
34
|
+
...rest,
|
|
35
|
+
amount: parseUnits(amount, decimals).toString(),
|
|
36
|
+
...chainId !== void 0 ? { methodDetails: { chainId } } : {}
|
|
37
|
+
}))
|
|
38
|
+
)
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
export {
|
|
43
|
+
charge
|
|
44
|
+
};
|
|
45
|
+
//# sourceMappingURL=chunk-CRRGQQSN.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/Methods.ts"],"sourcesContent":["import { Method, z } from \"mppx\";\nimport { parseUnits } from \"viem\";\n\n/**\n * 0G charge intent for one-time ERC-20 token transfers.\n */\nexport const charge = Method.from({\n name: \"zerog\",\n intent: \"charge\",\n schema: {\n credential: {\n payload: z.discriminatedUnion(\"type\", [\n z.object({ hash: z.hash(), type: z.literal(\"hash\") }),\n z.object({\n type: z.literal(\"authorization\"),\n from: z.string(),\n to: z.string(),\n value: z.string(),\n validAfter: z.string(),\n validBefore: z.string(),\n nonce: z.string(),\n signature: z.string(),\n }),\n ]),\n },\n request: z.pipe(\n z.object({\n amount: z.amount(),\n chainId: z.optional(z.number()),\n currency: z.string(),\n decimals: z.number(),\n description: z.optional(z.string()),\n externalId: z.optional(z.string()),\n recipient: z.optional(z.string()),\n }),\n z.transform(({ amount, chainId, decimals, ...rest }) => ({\n ...rest,\n amount: parseUnits(amount, decimals).toString(),\n ...(chainId !== undefined ? { methodDetails: { chainId } } : {}),\n }))\n ),\n },\n});\n"],"mappings":";AAAA,SAAS,QAAQ,SAAS;AAC1B,SAAS,kBAAkB;AAKpB,IAAM,SAAS,OAAO,KAAK;AAAA,EAChC,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,QAAQ;AAAA,IACN,YAAY;AAAA,MACV,SAAS,EAAE,mBAAmB,QAAQ;AAAA,QACpC,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,GAAG,MAAM,EAAE,QAAQ,MAAM,EAAE,CAAC;AAAA,QACpD,EAAE,OAAO;AAAA,UACP,MAAM,EAAE,QAAQ,eAAe;AAAA,UAC/B,MAAM,EAAE,OAAO;AAAA,UACf,IAAI,EAAE,OAAO;AAAA,UACb,OAAO,EAAE,OAAO;AAAA,UAChB,YAAY,EAAE,OAAO;AAAA,UACrB,aAAa,EAAE,OAAO;AAAA,UACtB,OAAO,EAAE,OAAO;AAAA,UAChB,WAAW,EAAE,OAAO;AAAA,QACtB,CAAC;AAAA,MACH,CAAC;AAAA,IACH;AAAA,IACA,SAAS,EAAE;AAAA,MACT,EAAE,OAAO;AAAA,QACP,QAAQ,EAAE,OAAO;AAAA,QACjB,SAAS,EAAE,SAAS,EAAE,OAAO,CAAC;AAAA,QAC9B,UAAU,EAAE,OAAO;AAAA,QACnB,UAAU,EAAE,OAAO;AAAA,QACnB,aAAa,EAAE,SAAS,EAAE,OAAO,CAAC;AAAA,QAClC,YAAY,EAAE,SAAS,EAAE,OAAO,CAAC;AAAA,QACjC,WAAW,EAAE,SAAS,EAAE,OAAO,CAAC;AAAA,MAClC,CAAC;AAAA,MACD,EAAE,UAAU,CAAC,EAAE,QAAQ,SAAS,UAAU,GAAG,KAAK,OAAO;AAAA,QACvD,GAAG;AAAA,QACH,QAAQ,WAAW,QAAQ,QAAQ,EAAE,SAAS;AAAA,QAC9C,GAAI,YAAY,SAAY,EAAE,eAAe,EAAE,QAAQ,EAAE,IAAI,CAAC;AAAA,MAChE,EAAE;AAAA,IACJ;AAAA,EACF;AACF,CAAC;","names":[]}
|