@avow-finance/verifier 0.0.0-stage → 0.2.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/LICENSE +201 -0
- package/README.md +112 -2
- package/dist/accept.d.ts +170 -0
- package/dist/accept.d.ts.map +1 -0
- package/dist/accept.js +268 -0
- package/dist/accept.js.map +1 -0
- package/dist/authorization.d.ts +65 -0
- package/dist/authorization.d.ts.map +1 -0
- package/dist/authorization.js +192 -0
- package/dist/authorization.js.map +1 -0
- package/dist/chain.d.ts +160 -0
- package/dist/chain.d.ts.map +1 -0
- package/dist/chain.js +72 -0
- package/dist/chain.js.map +1 -0
- package/dist/consent.d.ts +69 -0
- package/dist/consent.d.ts.map +1 -0
- package/dist/consent.js +98 -0
- package/dist/consent.js.map +1 -0
- package/dist/dependency.d.ts +252 -0
- package/dist/dependency.d.ts.map +1 -0
- package/dist/dependency.js +353 -0
- package/dist/dependency.js.map +1 -0
- package/dist/disclosure.d.ts +88 -0
- package/dist/disclosure.d.ts.map +1 -0
- package/dist/disclosure.js +210 -0
- package/dist/disclosure.js.map +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +17 -0
- package/dist/index.js.map +1 -0
- package/dist/issued.d.ts +5 -0
- package/dist/issued.d.ts.map +1 -0
- package/dist/issued.js +24 -0
- package/dist/issued.js.map +1 -0
- package/dist/lock-abi.d.ts +471 -0
- package/dist/lock-abi.d.ts.map +1 -0
- package/dist/lock-abi.js +452 -0
- package/dist/lock-abi.js.map +1 -0
- package/dist/nonce.d.ts +3 -0
- package/dist/nonce.d.ts.map +1 -0
- package/dist/nonce.js +4 -0
- package/dist/nonce.js.map +1 -0
- package/dist/references.d.ts +38 -0
- package/dist/references.d.ts.map +1 -0
- package/dist/references.js +93 -0
- package/dist/references.js.map +1 -0
- package/dist/report.d.ts +128 -0
- package/dist/report.d.ts.map +1 -0
- package/dist/report.js +155 -0
- package/dist/report.js.map +1 -0
- package/dist/signing.d.ts +47 -0
- package/dist/signing.d.ts.map +1 -0
- package/dist/signing.js +51 -0
- package/dist/signing.js.map +1 -0
- package/dist/tempo.d.ts +70 -0
- package/dist/tempo.d.ts.map +1 -0
- package/dist/tempo.js +341 -0
- package/dist/tempo.js.map +1 -0
- package/dist/verify.d.ts +65 -0
- package/dist/verify.d.ts.map +1 -0
- package/dist/verify.js +36 -0
- package/dist/verify.js.map +1 -0
- package/package.json +34 -3
package/dist/accept.js
ADDED
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
import { acceptanceTypedData, approvalCaps, approvalDigest, approvalJson, approvalMandateProblem, approvalPartiesProblem, approvalTermsProblem, approvalTokenProblem, digestOf, isChainedTerms, isTermsV1, lockTerms, parseSigned, termsShapeProblem, } from '@avow-finance/spec';
|
|
2
|
+
import { encodeFunctionData, isAddressEqual, isHex, size, zeroAddress, } from 'viem';
|
|
3
|
+
import { checkAuthorization, plainTerms, same, } from './authorization.js';
|
|
4
|
+
import { verifyDependencies, } from './dependency.js';
|
|
5
|
+
import { acceptanceDisclosure } from './disclosure.js';
|
|
6
|
+
import { issue } from './issued.js';
|
|
7
|
+
import { randomNonce } from './nonce.js';
|
|
8
|
+
import { signWithKey } from './signing.js';
|
|
9
|
+
/** An acceptance stays valid for ten minutes at most, and never past the acceptance deadline. */
|
|
10
|
+
export const ACCEPTANCE_VALIDITY = 600n;
|
|
11
|
+
const sameTiming = (a, b) => a.minContestWindow === b.minContestWindow &&
|
|
12
|
+
a.confirmWindow === b.confirmWindow &&
|
|
13
|
+
a.rulingDelay === b.rulingDelay &&
|
|
14
|
+
a.rulingKeyEnd === b.rulingKeyEnd &&
|
|
15
|
+
a.day90 === b.day90;
|
|
16
|
+
/**
|
|
17
|
+
* The supported way for a supplier to get an acceptance to sign. An acceptance binds the supplier
|
|
18
|
+
* to everything in Avow's approval, so this builds one only after every check passes, and refuses
|
|
19
|
+
* with the first reason that applies.
|
|
20
|
+
*
|
|
21
|
+
* 0. For version 3 terms, every booking they rely on passes `verifyDependencies` first, with the
|
|
22
|
+
* account Avow's approval names as supplier as the one whose lock has to hold it. That holds
|
|
23
|
+
* whoever the terms say checks for the buyer, since the supplier has the terms in full. Nothing
|
|
24
|
+
* below reads them before, and the checks below confirm the lock holds exactly that approval.
|
|
25
|
+
* 1. Avow's authorization passes every check `verifySupplierAuthorization` makes, with the buyer's
|
|
26
|
+
* signed mandate required, so a mandate that's forged, expired, revoked with its agent key, or
|
|
27
|
+
* that doesn't allow this supplier, category, currency, token or amount refuses.
|
|
28
|
+
* 2. Avow's approval names the commitment the supplier agreed to, the supplier's own account,
|
|
29
|
+
* signing key and payout, and the token, amount, deadlines, contest window, terms hash, charges,
|
|
30
|
+
* day-90 share and arbiter of the supplier's own terms.
|
|
31
|
+
* 3. It names the mandate Avow's authorization names, that mandate's two caps, and a funding key
|
|
32
|
+
* that's the mandate's agent key or the account's root key and that funded the reserve.
|
|
33
|
+
* 4. The lock stores the digest of exactly this approval and the same terms, and its token and
|
|
34
|
+
* dispute timing are the ones the supplier's profile accepts.
|
|
35
|
+
*
|
|
36
|
+
* It records nothing, since the lock takes one acceptance per reserve. What it returns is frozen,
|
|
37
|
+
* and `signAcceptance` signs nothing else. The checks protect a supplier who signs only through
|
|
38
|
+
* these two calls. The lock checks the signature and the digest, so it takes a correctly signed
|
|
39
|
+
* acceptance however it was built.
|
|
40
|
+
*
|
|
41
|
+
* Throws when the setup is wrong or the chain can't be read, as `verifySupplierAuthorization` does.
|
|
42
|
+
*/
|
|
43
|
+
export async function prepareAcceptance(request, deps) {
|
|
44
|
+
const { config, chain } = deps;
|
|
45
|
+
const refuse = (reason) => ({ ok: false, reason });
|
|
46
|
+
const t = request.terms;
|
|
47
|
+
if (!isChainedTerms(t)) {
|
|
48
|
+
const shape = termsShapeProblem(t);
|
|
49
|
+
if (shape)
|
|
50
|
+
return refuse(shape);
|
|
51
|
+
// Version 1 terms written before the dispute block existed can't be checked against the
|
|
52
|
+
// approval.
|
|
53
|
+
if (isTermsV1(t) && !t.dispute)
|
|
54
|
+
return refuse('terms.incomplete');
|
|
55
|
+
}
|
|
56
|
+
if (request.mandate === undefined || request.mandate === null)
|
|
57
|
+
return refuse('mandate.missing');
|
|
58
|
+
// The buyer and its mandate come from the agreement the supplier signed, so they're required.
|
|
59
|
+
const { buyerBusinessId, mandateHash: agreedMandate } = request.agreed ?? {};
|
|
60
|
+
if (typeof buyerBusinessId !== 'string' || !isHex(agreedMandate) || size(agreedMandate) !== 32) {
|
|
61
|
+
return refuse('message.invalid');
|
|
62
|
+
}
|
|
63
|
+
// Version 3 terms go no further until every booking they rely on passes. The checked terms the
|
|
64
|
+
// check gives back are the only way they reach the checks below.
|
|
65
|
+
let under;
|
|
66
|
+
let dependencies = [];
|
|
67
|
+
if (isChainedTerms(t)) {
|
|
68
|
+
// The owner comes from the approval, never from this supplier's own settings. The approval's
|
|
69
|
+
// envelope is read here and its lock and contents are checked below, so a check that passes
|
|
70
|
+
// here leads to an acceptance only once the lock is shown to hold this approval.
|
|
71
|
+
const named = parseSigned(request.approval, 'Approval', approvalJson, {
|
|
72
|
+
chainId: config.chainId,
|
|
73
|
+
});
|
|
74
|
+
if (!named.ok)
|
|
75
|
+
return named;
|
|
76
|
+
const relied = await verifyDependencies({
|
|
77
|
+
terms: t,
|
|
78
|
+
approval: named.value.message,
|
|
79
|
+
disclosed: request.disclosed ?? [],
|
|
80
|
+
now: request.now,
|
|
81
|
+
}, deps.dependencies ?? { readers: [] });
|
|
82
|
+
if (!relied.ok)
|
|
83
|
+
return relied;
|
|
84
|
+
under = { kind: 'chained', terms: relied.terms };
|
|
85
|
+
dependencies = relied.checked;
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
under = { kind: 'plain', terms: t };
|
|
89
|
+
}
|
|
90
|
+
const checked = await checkAuthorization({
|
|
91
|
+
authorization: request.authorization,
|
|
92
|
+
agreed: request.agreed,
|
|
93
|
+
terms: under,
|
|
94
|
+
mandate: request.mandate,
|
|
95
|
+
now: request.now,
|
|
96
|
+
}, config, chain);
|
|
97
|
+
if (!checked.ok)
|
|
98
|
+
return checked;
|
|
99
|
+
const { authorization: auth, lock, domain: d, lockInfo, backing, token, mandate } = checked;
|
|
100
|
+
if (!mandate)
|
|
101
|
+
return refuse('mandate.missing');
|
|
102
|
+
const parsed = parseSigned(request.approval, 'Approval', approvalJson, {
|
|
103
|
+
chainId: config.chainId,
|
|
104
|
+
lock,
|
|
105
|
+
});
|
|
106
|
+
if (!parsed.ok)
|
|
107
|
+
return parsed;
|
|
108
|
+
const a = parsed.value.message;
|
|
109
|
+
// The approval against the supplier's own records.
|
|
110
|
+
if (!same(a.commitmentId, request.agreed.commitmentId)) {
|
|
111
|
+
return refuse('approval.commitment_mismatch');
|
|
112
|
+
}
|
|
113
|
+
const parties = approvalPartiesProblem(a, config);
|
|
114
|
+
if (parties)
|
|
115
|
+
return refuse(parties);
|
|
116
|
+
let enforced;
|
|
117
|
+
let caps;
|
|
118
|
+
try {
|
|
119
|
+
enforced = lockTerms(plainTerms(under), token.decimals);
|
|
120
|
+
caps = approvalCaps(mandate, token.decimals);
|
|
121
|
+
}
|
|
122
|
+
catch {
|
|
123
|
+
return refuse('authorization.token_not_accepted');
|
|
124
|
+
}
|
|
125
|
+
if (a.side !== 'buyer')
|
|
126
|
+
return refuse('approval.terms_mismatch');
|
|
127
|
+
const tokenProblem = approvalTokenProblem(a, token.token);
|
|
128
|
+
if (tokenProblem)
|
|
129
|
+
return refuse(tokenProblem);
|
|
130
|
+
// Every field the lock enforces has to be what the supplier's own terms map to, through the
|
|
131
|
+
// same mapping Avow's API signs with, under the terms hash the supplier agreed to.
|
|
132
|
+
const differs = approvalTermsProblem(a, {
|
|
133
|
+
lock: enforced,
|
|
134
|
+
termsHash: request.agreed.termsHash,
|
|
135
|
+
});
|
|
136
|
+
if (differs)
|
|
137
|
+
return refuse(differs);
|
|
138
|
+
// The approval against the buyer's mandate and Avow's authorization. The reserve may come from
|
|
139
|
+
// the mandate's agent key or the account's root key.
|
|
140
|
+
const mandateProblem = approvalMandateProblem(a, {
|
|
141
|
+
mandateHash: auth.mandateHash,
|
|
142
|
+
caps,
|
|
143
|
+
fundingKeys: [mandate.agentKey, zeroAddress],
|
|
144
|
+
});
|
|
145
|
+
if (mandateProblem)
|
|
146
|
+
return refuse(mandateProblem);
|
|
147
|
+
// And it has to name the key that funded the reserve.
|
|
148
|
+
if (!isAddressEqual(a.fundingKey, backing.fundingKey))
|
|
149
|
+
return refuse('approval.mandate_mismatch');
|
|
150
|
+
// The lock holds this exact approval, under settings the supplier accepts.
|
|
151
|
+
const approvalHash = approvalDigest(a, d);
|
|
152
|
+
if (!same(backing.approvalHash, approvalHash) || !holdsApproval(backing, a)) {
|
|
153
|
+
return refuse('chain.approval_mismatch');
|
|
154
|
+
}
|
|
155
|
+
if (!isAddressEqual(lockInfo.token, a.token) ||
|
|
156
|
+
!sameTiming(lockInfo.timing, config.profile.lockTiming)) {
|
|
157
|
+
return refuse('chain.lock_timing_unexpected');
|
|
158
|
+
}
|
|
159
|
+
const latest = request.now + ACCEPTANCE_VALIDITY;
|
|
160
|
+
const acceptance = {
|
|
161
|
+
commitmentId: a.commitmentId,
|
|
162
|
+
side: 'buyer',
|
|
163
|
+
approvalHash,
|
|
164
|
+
termsHash: a.termsHash,
|
|
165
|
+
amount: a.amount,
|
|
166
|
+
token: a.token,
|
|
167
|
+
acceptBy: a.acceptBy,
|
|
168
|
+
nonce: request.nonce ?? randomNonce(),
|
|
169
|
+
expiry: latest < a.acceptBy ? latest : a.acceptBy,
|
|
170
|
+
};
|
|
171
|
+
const digest = digestOf(acceptanceTypedData(acceptance, d));
|
|
172
|
+
return issue({
|
|
173
|
+
ok: true,
|
|
174
|
+
acceptance,
|
|
175
|
+
domain: d,
|
|
176
|
+
digest,
|
|
177
|
+
approvalDigest: approvalHash,
|
|
178
|
+
signingKey: config.signingKey,
|
|
179
|
+
disclosure: acceptanceDisclosure({
|
|
180
|
+
digest,
|
|
181
|
+
expiry: acceptance.expiry,
|
|
182
|
+
approval: a,
|
|
183
|
+
approvalDigest: approvalHash,
|
|
184
|
+
lock,
|
|
185
|
+
chainId: config.chainId,
|
|
186
|
+
account: lockInfo.account,
|
|
187
|
+
token,
|
|
188
|
+
timing: lockInfo.timing,
|
|
189
|
+
}),
|
|
190
|
+
dependencies,
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
/** Whether the lock's record names the approval's parties, terms hash and mandate hash. */
|
|
194
|
+
function holdsApproval(b, a) {
|
|
195
|
+
// Its lock-enforced fields already match, since the record and the approval each match the terms.
|
|
196
|
+
return (isAddressEqual(b.payee, a.payee) &&
|
|
197
|
+
isAddressEqual(b.supplier, a.supplier) &&
|
|
198
|
+
isAddressEqual(b.supplierSigner, a.supplierSigner) &&
|
|
199
|
+
same(b.termsHash, a.termsHash) &&
|
|
200
|
+
same(b.mandateHash, a.mandateHash));
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Signs an acceptance with the supplier's signing key, once the person has seen its disclosure. It
|
|
204
|
+
* signs only the object `prepareAcceptance` returned, which is frozen, so a copy or an edit of it
|
|
205
|
+
* throws. It also throws when the confirmation names another disclosure, or when the key isn't
|
|
206
|
+
* the signing key Avow's approval names.
|
|
207
|
+
*/
|
|
208
|
+
export function signAcceptance(prepared, key, confirmation) {
|
|
209
|
+
return signWithKey({
|
|
210
|
+
prepared,
|
|
211
|
+
typedData: acceptanceTypedData(prepared.acceptance, prepared.domain),
|
|
212
|
+
message: prepared.acceptance,
|
|
213
|
+
key,
|
|
214
|
+
confirmation,
|
|
215
|
+
names: {
|
|
216
|
+
message: 'acceptance',
|
|
217
|
+
prepare: 'prepareAcceptance',
|
|
218
|
+
signingKey: "the signing key Avow's approval names",
|
|
219
|
+
},
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* The lock's `accept`, as the testnet lock declares it. Anyone can send it, since the lock checks
|
|
224
|
+
* the supplier's signing key signed the acceptance, so a supplier can send it from any account
|
|
225
|
+
* that pays the fee.
|
|
226
|
+
*/
|
|
227
|
+
export const ACCEPT_ABI = [
|
|
228
|
+
{
|
|
229
|
+
type: 'function',
|
|
230
|
+
name: 'accept',
|
|
231
|
+
inputs: [
|
|
232
|
+
{
|
|
233
|
+
name: 'm',
|
|
234
|
+
type: 'tuple',
|
|
235
|
+
components: [
|
|
236
|
+
{ name: 'commitmentId', type: 'bytes32' },
|
|
237
|
+
{ name: 'side', type: 'uint8' },
|
|
238
|
+
{ name: 'approvalHash', type: 'bytes32' },
|
|
239
|
+
{ name: 'termsHash', type: 'bytes32' },
|
|
240
|
+
{ name: 'amount', type: 'uint256' },
|
|
241
|
+
{ name: 'token', type: 'address' },
|
|
242
|
+
{ name: 'acceptBy', type: 'uint64' },
|
|
243
|
+
{ name: 'nonce', type: 'uint256' },
|
|
244
|
+
{ name: 'expiry', type: 'uint64' },
|
|
245
|
+
],
|
|
246
|
+
},
|
|
247
|
+
{ name: 'signature', type: 'bytes' },
|
|
248
|
+
],
|
|
249
|
+
outputs: [],
|
|
250
|
+
stateMutability: 'nonpayable',
|
|
251
|
+
},
|
|
252
|
+
];
|
|
253
|
+
/**
|
|
254
|
+
* The call that hands a signed acceptance to its lock, with the fields exactly as they were signed,
|
|
255
|
+
* so the lock checks the same digest the supplier's key signed.
|
|
256
|
+
*/
|
|
257
|
+
export function acceptCall(acceptance) {
|
|
258
|
+
const d = { chainId: acceptance.chainId, verifyingContract: acceptance.lock };
|
|
259
|
+
return {
|
|
260
|
+
to: acceptance.lock,
|
|
261
|
+
data: encodeFunctionData({
|
|
262
|
+
abi: ACCEPT_ABI,
|
|
263
|
+
functionName: 'accept',
|
|
264
|
+
args: [acceptanceTypedData(acceptance.message, d).message, acceptance.signature],
|
|
265
|
+
}),
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
//# sourceMappingURL=accept.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"accept.js","sourceRoot":"","sources":["../src/accept.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { type AnyTerms, type AvowDomain, type Mandate, type RailToken, type ReasonCode, type SupplierAuthorization } from '@avow-finance/spec';
|
|
2
|
+
import { type Address, type Hex } from 'viem';
|
|
3
|
+
import type { ChainReader, LockedBacking, LockInfo } from './chain.js';
|
|
4
|
+
import type { CheckedChainedTerms } from './dependency.js';
|
|
5
|
+
import type { VerifierConfig } from './verify.js';
|
|
6
|
+
/** Avow signs a supplier authorization for five minutes. */
|
|
7
|
+
export declare const AUTHORIZATION_VALIDITY = 300n;
|
|
8
|
+
/** What the supplier agreed to, from the terms agreement it signed. */
|
|
9
|
+
export interface Agreed {
|
|
10
|
+
commitmentId: Hex;
|
|
11
|
+
termsHash: Hex;
|
|
12
|
+
category: string;
|
|
13
|
+
/** The buyer the agreement names. Checked when given. */
|
|
14
|
+
buyerBusinessId?: string;
|
|
15
|
+
/** The buyer's mandate the agreement names, which also names the buyer's lock. Checked when given. */
|
|
16
|
+
mandateHash?: Hex;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* The supplier's own terms, as an authorization is checked against them. Plain terms are version
|
|
20
|
+
* 2, or version 1 for a commitment made under it. Chained terms are version 3 terms every booking
|
|
21
|
+
* of which passed `verifyDependencies`, which only that check gives.
|
|
22
|
+
*/
|
|
23
|
+
export type TermsUnderCheck = {
|
|
24
|
+
kind: 'plain';
|
|
25
|
+
terms: AnyTerms;
|
|
26
|
+
} | {
|
|
27
|
+
kind: 'chained';
|
|
28
|
+
terms: CheckedChainedTerms;
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* The terms the rules, the mandate and the lock read. Version 3 terms make the plain booking
|
|
32
|
+
* `plainTermsOf` gives, since the lock enforces nothing in their dependencies section.
|
|
33
|
+
*/
|
|
34
|
+
export declare function plainTerms(under: TermsUnderCheck): AnyTerms;
|
|
35
|
+
export interface AuthorizationInput {
|
|
36
|
+
authorization: unknown;
|
|
37
|
+
agreed: Agreed;
|
|
38
|
+
terms: TermsUnderCheck;
|
|
39
|
+
mandate?: unknown;
|
|
40
|
+
now: bigint;
|
|
41
|
+
}
|
|
42
|
+
export type AuthorizationCheck = {
|
|
43
|
+
ok: true;
|
|
44
|
+
authorization: SupplierAuthorization;
|
|
45
|
+
lock: Address;
|
|
46
|
+
domain: AvowDomain;
|
|
47
|
+
lockInfo: LockInfo;
|
|
48
|
+
backing: LockedBacking;
|
|
49
|
+
token: RailToken;
|
|
50
|
+
/** The buyer's mandate, when the caller passed it and it passed. */
|
|
51
|
+
mandate: Mandate | null;
|
|
52
|
+
signer: Address;
|
|
53
|
+
} | {
|
|
54
|
+
ok: false;
|
|
55
|
+
reason: ReasonCode;
|
|
56
|
+
};
|
|
57
|
+
/** Equal hex values in any letter case. Anything that isn't a string is never equal. */
|
|
58
|
+
export declare const same: (a: Hex, b: Hex) => boolean;
|
|
59
|
+
/**
|
|
60
|
+
* Every check of a supplier authorization except the record that it passed, which only
|
|
61
|
+
* `verifySupplierAuthorization` makes. `prepareAcceptance` runs the same checks again with the
|
|
62
|
+
* buyer's mandate required.
|
|
63
|
+
*/
|
|
64
|
+
export declare function checkAuthorization(input: AuthorizationInput, config: VerifierConfig, chain: ChainReader): Promise<AuthorizationCheck>;
|
|
65
|
+
//# sourceMappingURL=authorization.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authorization.d.ts","sourceRoot":"","sources":["../src/authorization.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,QAAQ,EAEb,KAAK,UAAU,EASf,KAAK,OAAO,EAMZ,KAAK,SAAS,EACd,KAAK,UAAU,EACf,KAAK,qBAAqB,EAO3B,MAAM,oBAAoB,CAAA;AAC3B,OAAO,EAAE,KAAK,OAAO,EAAE,KAAK,GAAG,EAA+C,MAAM,MAAM,CAAA;AAC1F,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AACtE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAA;AAC1D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAEjD,4DAA4D;AAC5D,eAAO,MAAM,sBAAsB,OAAO,CAAA;AAI1C,uEAAuE;AACvE,MAAM,WAAW,MAAM;IACrB,YAAY,EAAE,GAAG,CAAA;IACjB,SAAS,EAAE,GAAG,CAAA;IACd,QAAQ,EAAE,MAAM,CAAA;IAChB,yDAAyD;IACzD,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,sGAAsG;IACtG,WAAW,CAAC,EAAE,GAAG,CAAA;CAClB;AAED;;;;GAIG;AACH,MAAM,MAAM,eAAe,GACvB;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,QAAQ,CAAA;CAAE,GAClC;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,KAAK,EAAE,mBAAmB,CAAA;CAAE,CAAA;AAEnD;;;GAGG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,eAAe,GAAG,QAAQ,CAE3D;AAED,MAAM,WAAW,kBAAkB;IACjC,aAAa,EAAE,OAAO,CAAA;IACtB,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,eAAe,CAAA;IACtB,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,GAAG,EAAE,MAAM,CAAA;CACZ;AAED,MAAM,MAAM,kBAAkB,GAC1B;IACE,EAAE,EAAE,IAAI,CAAA;IACR,aAAa,EAAE,qBAAqB,CAAA;IACpC,IAAI,EAAE,OAAO,CAAA;IACb,MAAM,EAAE,UAAU,CAAA;IAClB,QAAQ,EAAE,QAAQ,CAAA;IAClB,OAAO,EAAE,aAAa,CAAA;IACtB,KAAK,EAAE,SAAS,CAAA;IAChB,oEAAoE;IACpE,OAAO,EAAE,OAAO,GAAG,IAAI,CAAA;IACvB,MAAM,EAAE,OAAO,CAAA;CAChB,GACD;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,UAAU,CAAA;CAAE,CAAA;AAErC,wFAAwF;AACxF,eAAO,MAAM,IAAI,MAAO,GAAG,KAAK,GAAG,YACoD,CAAA;AAEvF;;;;GAIG;AACH,wBAAsB,kBAAkB,CACtC,KAAK,EAAE,kBAAkB,EACzB,MAAM,EAAE,cAAc,EACtB,KAAK,EAAE,WAAW,GACjB,OAAO,CAAC,kBAAkB,CAAC,CA8K7B"}
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import { AUTHORIZATION_TERMS_FIELDS, assertTestSettingsOnTestnet, checkMandate, digestOf, enforceableTerms, lockRecordDifferences, lockTerms, lockTermsDifferences, mandateHash, mandateJson, mandateTypedData, parseSigned, plainTermsOf, supplierAuthorizationJson, supplierAuthorizationTypedData, termsHash, termsShapeProblem, validateChainedTerms, validateTerms, } from '@avow-finance/spec';
|
|
2
|
+
import { isAddressEqual, recoverAddress, zeroAddress } from 'viem';
|
|
3
|
+
/** Avow signs a supplier authorization for five minutes. */
|
|
4
|
+
export const AUTHORIZATION_VALIDITY = 300n;
|
|
5
|
+
/** Room for the supplier's clock to run behind Avow's. */
|
|
6
|
+
const CLOCK_ALLOWANCE = 60n;
|
|
7
|
+
/**
|
|
8
|
+
* The terms the rules, the mandate and the lock read. Version 3 terms make the plain booking
|
|
9
|
+
* `plainTermsOf` gives, since the lock enforces nothing in their dependencies section.
|
|
10
|
+
*/
|
|
11
|
+
export function plainTerms(under) {
|
|
12
|
+
return under.kind === 'plain' ? under.terms : plainTermsOf(under.terms);
|
|
13
|
+
}
|
|
14
|
+
/** Equal hex values in any letter case. Anything that isn't a string is never equal. */
|
|
15
|
+
export const same = (a, b) => typeof a === 'string' && typeof b === 'string' && a.toLowerCase() === b.toLowerCase();
|
|
16
|
+
/**
|
|
17
|
+
* Every check of a supplier authorization except the record that it passed, which only
|
|
18
|
+
* `verifySupplierAuthorization` makes. `prepareAcceptance` runs the same checks again with the
|
|
19
|
+
* buyer's mandate required.
|
|
20
|
+
*/
|
|
21
|
+
export async function checkAuthorization(input, config, chain) {
|
|
22
|
+
if (chain.chainId !== config.chainId) {
|
|
23
|
+
throw new Error(`The chain reader is for chain ${chain.chainId}, not ${config.chainId}`);
|
|
24
|
+
}
|
|
25
|
+
assertTestSettingsOnTestnet({
|
|
26
|
+
chainId: config.chainId,
|
|
27
|
+
testData: config.acceptTestData,
|
|
28
|
+
profile: config.profile,
|
|
29
|
+
});
|
|
30
|
+
const refuse = (reason) => ({ ok: false, reason });
|
|
31
|
+
// The envelope, the signature and the validity window.
|
|
32
|
+
const parsed = parseSigned(input.authorization, 'SupplierAuthorization', supplierAuthorizationJson, { chainId: config.chainId });
|
|
33
|
+
if (!parsed.ok)
|
|
34
|
+
return parsed;
|
|
35
|
+
const { message: auth, lock, signature } = parsed.value;
|
|
36
|
+
if (auth.expiry <= input.now)
|
|
37
|
+
return refuse('message.expired');
|
|
38
|
+
const maxValidity = config.maxValidity ?? AUTHORIZATION_VALIDITY;
|
|
39
|
+
if (auth.expiry > input.now + maxValidity + CLOCK_ALLOWANCE) {
|
|
40
|
+
return refuse('message.validity_too_long');
|
|
41
|
+
}
|
|
42
|
+
const d = { chainId: config.chainId, verifyingContract: lock };
|
|
43
|
+
let signer;
|
|
44
|
+
try {
|
|
45
|
+
signer = await recoverAddress({
|
|
46
|
+
hash: digestOf(supplierAuthorizationTypedData(auth, d)),
|
|
47
|
+
signature,
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
return refuse('message.signature_invalid');
|
|
52
|
+
}
|
|
53
|
+
if (!config.avowKeys.some((k) => isAddressEqual(k, signer))) {
|
|
54
|
+
return refuse('message.signer_unknown');
|
|
55
|
+
}
|
|
56
|
+
// The commitment the supplier agreed to, and nothing else.
|
|
57
|
+
if (!same(auth.commitmentId, input.agreed.commitmentId)) {
|
|
58
|
+
return refuse('authorization.commitment_mismatch');
|
|
59
|
+
}
|
|
60
|
+
if (!same(auth.termsHash, input.agreed.termsHash))
|
|
61
|
+
return refuse('terms.hash_mismatch');
|
|
62
|
+
const { buyerBusinessId, mandateHash: agreedMandate } = input.agreed;
|
|
63
|
+
if (buyerBusinessId !== undefined && auth.buyerBusinessId !== buyerBusinessId) {
|
|
64
|
+
return refuse('authorization.buyer_mismatch');
|
|
65
|
+
}
|
|
66
|
+
if (agreedMandate !== undefined && !same(auth.mandateHash, agreedMandate)) {
|
|
67
|
+
return refuse('authorization.mandate_mismatch');
|
|
68
|
+
}
|
|
69
|
+
if (auth.kybTestData && !config.acceptTestData)
|
|
70
|
+
return refuse('business.test_data');
|
|
71
|
+
// The supplier's terms against the ones Avow signed, once they have a shape the hash covers.
|
|
72
|
+
const under = input.terms;
|
|
73
|
+
// Checked version 3 terms passed their shape check in `verifyDependencies`.
|
|
74
|
+
if (under.kind === 'plain') {
|
|
75
|
+
const shape = termsShapeProblem(under.terms);
|
|
76
|
+
if (shape)
|
|
77
|
+
return refuse(shape);
|
|
78
|
+
}
|
|
79
|
+
if (!same(termsHash(under.terms, auth.salt), auth.termsHash))
|
|
80
|
+
return refuse('terms.hash_mismatch');
|
|
81
|
+
const termsProblem = under.kind === 'plain'
|
|
82
|
+
? validateTerms(under.terms, config.profile)
|
|
83
|
+
: validateChainedTerms(under.terms, config.profile);
|
|
84
|
+
if (termsProblem)
|
|
85
|
+
return refuse(termsProblem);
|
|
86
|
+
const t = plainTerms(under);
|
|
87
|
+
// What the lock enforces, read from the supplier's terms the way Avow's API reads them.
|
|
88
|
+
const e = enforceableTerms(t);
|
|
89
|
+
const token = config.acceptedTokens.find((a) => a.chainId === config.chainId &&
|
|
90
|
+
isAddressEqual(a.token, auth.token) &&
|
|
91
|
+
a.currency === e.currency);
|
|
92
|
+
if (!token)
|
|
93
|
+
return refuse('authorization.token_not_accepted');
|
|
94
|
+
// Every value the lock enforces, in the token's base units.
|
|
95
|
+
let expected;
|
|
96
|
+
try {
|
|
97
|
+
expected = lockTerms(t, token.decimals);
|
|
98
|
+
}
|
|
99
|
+
catch {
|
|
100
|
+
return refuse('authorization.token_not_accepted');
|
|
101
|
+
}
|
|
102
|
+
if (lockTermsDifferences(auth, expected, AUTHORIZATION_TERMS_FIELDS).length > 0) {
|
|
103
|
+
return refuse('authorization.terms_mismatch');
|
|
104
|
+
}
|
|
105
|
+
if (!isAddressEqual(auth.payee, config.payee))
|
|
106
|
+
return refuse('authorization.payee_mismatch');
|
|
107
|
+
if (auth.acceptBy <= input.now)
|
|
108
|
+
return refuse('authorization.accept_by_passed');
|
|
109
|
+
// The chain, read directly.
|
|
110
|
+
const lockInfo = await chain.lock(lock);
|
|
111
|
+
if (!lockInfo?.fromFactory)
|
|
112
|
+
return refuse('chain.lock_unknown');
|
|
113
|
+
const backing = await chain.backing(lock, auth.commitmentId, 'buyer');
|
|
114
|
+
if (backing?.state === 'accepted')
|
|
115
|
+
return refuse('chain.reserve_accepted');
|
|
116
|
+
if (backing?.state !== 'reserved')
|
|
117
|
+
return refuse('chain.reserve_missing');
|
|
118
|
+
const fundedByAgentOrRoot = isAddressEqual(backing.fundingKey, auth.agentKey) ||
|
|
119
|
+
isAddressEqual(backing.fundingKey, zeroAddress);
|
|
120
|
+
// The lock's record has to hold Avow's authorization and enforce exactly what the terms map to,
|
|
121
|
+
// in every field it stores.
|
|
122
|
+
if (!isAddressEqual(backing.token, auth.token) ||
|
|
123
|
+
!isAddressEqual(backing.payee, auth.payee) ||
|
|
124
|
+
!same(backing.termsHash, auth.termsHash) ||
|
|
125
|
+
!fundedByAgentOrRoot ||
|
|
126
|
+
lockRecordDifferences(backing, expected).length > 0) {
|
|
127
|
+
return refuse('chain.reserve_mismatch');
|
|
128
|
+
}
|
|
129
|
+
const key = await chain.agentKey(lockInfo.account, auth.agentKey, auth.agentKeyAuthorizedIn);
|
|
130
|
+
if (!key?.active)
|
|
131
|
+
return refuse('chain.agent_key_inactive');
|
|
132
|
+
// The key has to last until nothing more can happen to the commitment.
|
|
133
|
+
if (key.expiry !== null && key.expiry < e.releaseDate)
|
|
134
|
+
return refuse('chain.agent_key_inactive');
|
|
135
|
+
if (key.witness === null || !same(key.witness, auth.mandateHash)) {
|
|
136
|
+
return refuse('chain.mandate_mismatch');
|
|
137
|
+
}
|
|
138
|
+
// The buyer's mandate, when the supplier has it: its hash, its signer and its limits.
|
|
139
|
+
let mandate = null;
|
|
140
|
+
if (input.mandate !== undefined) {
|
|
141
|
+
const m = parseSigned(input.mandate, 'Mandate', mandateJson, {
|
|
142
|
+
chainId: config.chainId,
|
|
143
|
+
lock,
|
|
144
|
+
});
|
|
145
|
+
if (!m.ok)
|
|
146
|
+
return m;
|
|
147
|
+
mandate = m.value.message;
|
|
148
|
+
if (!same(mandateHash(mandate, d), auth.mandateHash) ||
|
|
149
|
+
mandate.businessId !== auth.buyerBusinessId ||
|
|
150
|
+
!isAddressEqual(mandate.account, lockInfo.account) ||
|
|
151
|
+
!isAddressEqual(mandate.agentKey, auth.agentKey)) {
|
|
152
|
+
return refuse('authorization.mandate_mismatch');
|
|
153
|
+
}
|
|
154
|
+
const signed = await chain.isAccountSignature(lockInfo.account, digestOf(mandateTypedData(mandate, d)), m.value.signature);
|
|
155
|
+
if (!signed)
|
|
156
|
+
return refuse('mandate.signature_invalid');
|
|
157
|
+
// The parts a supplier can check. Open reserves and revocation live with the lock and the
|
|
158
|
+
// key, which the checks above read, and Avow's signature stands for any human approval.
|
|
159
|
+
const limits = checkMandate({
|
|
160
|
+
mandate,
|
|
161
|
+
request: {
|
|
162
|
+
commitmentId: auth.commitmentId,
|
|
163
|
+
agentKey: auth.agentKey,
|
|
164
|
+
supplier: config.businessId,
|
|
165
|
+
payee: auth.payee,
|
|
166
|
+
category: input.agreed.category,
|
|
167
|
+
// Checked version 3 terms go in whole. Their plain booking alone would fail a template
|
|
168
|
+
// that commits only on a booking it relies on, as a job does.
|
|
169
|
+
terms: under.terms,
|
|
170
|
+
},
|
|
171
|
+
token,
|
|
172
|
+
openReserves: 0n,
|
|
173
|
+
revoked: false,
|
|
174
|
+
now: input.now,
|
|
175
|
+
profile: config.profile,
|
|
176
|
+
});
|
|
177
|
+
if (limits.result === 'denied')
|
|
178
|
+
return refuse(limits.reason);
|
|
179
|
+
}
|
|
180
|
+
return {
|
|
181
|
+
ok: true,
|
|
182
|
+
authorization: auth,
|
|
183
|
+
lock,
|
|
184
|
+
domain: d,
|
|
185
|
+
lockInfo,
|
|
186
|
+
backing,
|
|
187
|
+
token,
|
|
188
|
+
mandate,
|
|
189
|
+
signer,
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
//# sourceMappingURL=authorization.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authorization.js","sourceRoot":"","sources":["../src/authorization.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,0BAA0B,EAE1B,2BAA2B,EAC3B,YAAY,EACZ,QAAQ,EACR,gBAAgB,EAEhB,qBAAqB,EACrB,SAAS,EACT,oBAAoB,EAEpB,WAAW,EACX,WAAW,EACX,gBAAgB,EAChB,WAAW,EACX,YAAY,EAIZ,yBAAyB,EACzB,8BAA8B,EAC9B,SAAS,EACT,iBAAiB,EACjB,oBAAoB,EACpB,aAAa,GACd,MAAM,oBAAoB,CAAA;AAC3B,OAAO,EAA0B,cAAc,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,MAAM,CAAA;AAK1F,4DAA4D;AAC5D,MAAM,CAAC,MAAM,sBAAsB,GAAG,IAAI,CAAA;AAC1C,0DAA0D;AAC1D,MAAM,eAAe,GAAG,GAAG,CAAA;AAsB3B;;;GAGG;AACH,MAAM,UAAU,UAAU,CAAC,KAAsB;IAC/C,OAAO,KAAK,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,YAAY,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;AACzE,CAAC;AAyBD,wFAAwF;AACxF,MAAM,CAAC,MAAM,IAAI,GAAG,CAAC,CAAM,EAAE,CAAM,EAAE,EAAE,CACrC,OAAO,CAAC,KAAK,QAAQ,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC,WAAW,EAAE,CAAA;AAEvF;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,KAAyB,EACzB,MAAsB,EACtB,KAAkB;IAElB,IAAI,KAAK,CAAC,OAAO,KAAK,MAAM,CAAC,OAAO,EAAE,CAAC;QACrC,MAAM,IAAI,KAAK,CAAC,iCAAiC,KAAK,CAAC,OAAO,SAAS,MAAM,CAAC,OAAO,EAAE,CAAC,CAAA;IAC1F,CAAC;IACD,2BAA2B,CAAC;QAC1B,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,QAAQ,EAAE,MAAM,CAAC,cAAc;QAC/B,OAAO,EAAE,MAAM,CAAC,OAAO;KACxB,CAAC,CAAA;IACF,MAAM,MAAM,GAAG,CAAC,MAAkB,EAAsB,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAA;IAElF,uDAAuD;IACvD,MAAM,MAAM,GAAG,WAAW,CACxB,KAAK,CAAC,aAAa,EACnB,uBAAuB,EACvB,yBAAyB,EACzB,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,CAC5B,CAAA;IACD,IAAI,CAAC,MAAM,CAAC,EAAE;QAAE,OAAO,MAAM,CAAA;IAC7B,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,MAAM,CAAC,KAAK,CAAA;IACvD,IAAI,IAAI,CAAC,MAAM,IAAI,KAAK,CAAC,GAAG;QAAE,OAAO,MAAM,CAAC,iBAAiB,CAAC,CAAA;IAC9D,MAAM,WAAW,GAAG,MAAM,CAAC,WAAW,IAAI,sBAAsB,CAAA;IAChE,IAAI,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC,GAAG,GAAG,WAAW,GAAG,eAAe,EAAE,CAAC;QAC5D,OAAO,MAAM,CAAC,2BAA2B,CAAC,CAAA;IAC5C,CAAC;IACD,MAAM,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,iBAAiB,EAAE,IAAI,EAAE,CAAA;IAC9D,IAAI,MAAe,CAAA;IACnB,IAAI,CAAC;QACH,MAAM,GAAG,MAAM,cAAc,CAAC;YAC5B,IAAI,EAAE,QAAQ,CAAC,8BAA8B,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;YACvD,SAAS;SACV,CAAC,CAAA;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,MAAM,CAAC,2BAA2B,CAAC,CAAA;IAC5C,CAAC;IACD,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,cAAc,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC;QAC5D,OAAO,MAAM,CAAC,wBAAwB,CAAC,CAAA;IACzC,CAAC;IAED,2DAA2D;IAC3D,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,EAAE,CAAC;QACxD,OAAO,MAAM,CAAC,mCAAmC,CAAC,CAAA;IACpD,CAAC;IACD,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC;QAAE,OAAO,MAAM,CAAC,qBAAqB,CAAC,CAAA;IACvF,MAAM,EAAE,eAAe,EAAE,WAAW,EAAE,aAAa,EAAE,GAAG,KAAK,CAAC,MAAM,CAAA;IACpE,IAAI,eAAe,KAAK,SAAS,IAAI,IAAI,CAAC,eAAe,KAAK,eAAe,EAAE,CAAC;QAC9E,OAAO,MAAM,CAAC,8BAA8B,CAAC,CAAA;IAC/C,CAAC;IACD,IAAI,aAAa,KAAK,SAAS,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,aAAa,CAAC,EAAE,CAAC;QAC1E,OAAO,MAAM,CAAC,gCAAgC,CAAC,CAAA;IACjD,CAAC;IACD,IAAI,IAAI,CAAC,WAAW,IAAI,CAAC,MAAM,CAAC,cAAc;QAAE,OAAO,MAAM,CAAC,oBAAoB,CAAC,CAAA;IAEnF,6FAA6F;IAC7F,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAA;IACzB,4EAA4E;IAC5E,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;QAC3B,MAAM,KAAK,GAAG,iBAAiB,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;QAC5C,IAAI,KAAK;YAAE,OAAO,MAAM,CAAC,KAAK,CAAC,CAAA;IACjC,CAAC;IACD,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC;QAAE,OAAO,MAAM,CAAC,qBAAqB,CAAC,CAAA;IAClG,MAAM,YAAY,GAChB,KAAK,CAAC,IAAI,KAAK,OAAO;QACpB,CAAC,CAAC,aAAa,CAAC,KAAK,CAAC,KAAK,EAAE,MAAM,CAAC,OAAO,CAAC;QAC5C,CAAC,CAAC,oBAAoB,CAAC,KAAK,CAAC,KAAK,EAAE,MAAM,CAAC,OAAO,CAAC,CAAA;IACvD,IAAI,YAAY;QAAE,OAAO,MAAM,CAAC,YAAY,CAAC,CAAA;IAC7C,MAAM,CAAC,GAAG,UAAU,CAAC,KAAK,CAAC,CAAA;IAC3B,wFAAwF;IACxF,MAAM,CAAC,GAAG,gBAAgB,CAAC,CAAC,CAAC,CAAA;IAC7B,MAAM,KAAK,GAAG,MAAM,CAAC,cAAc,CAAC,IAAI,CACtC,CAAC,CAAC,EAAE,EAAE,CACJ,CAAC,CAAC,OAAO,KAAK,MAAM,CAAC,OAAO;QAC5B,cAAc,CAAC,CAAC,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC;QACnC,CAAC,CAAC,QAAQ,KAAK,CAAC,CAAC,QAAQ,CAC5B,CAAA;IACD,IAAI,CAAC,KAAK;QAAE,OAAO,MAAM,CAAC,kCAAkC,CAAC,CAAA;IAC7D,4DAA4D;IAC5D,IAAI,QAAmB,CAAA;IACvB,IAAI,CAAC;QACH,QAAQ,GAAG,SAAS,CAAC,CAAC,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAA;IACzC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,MAAM,CAAC,kCAAkC,CAAC,CAAA;IACnD,CAAC;IACD,IAAI,oBAAoB,CAAC,IAAI,EAAE,QAAQ,EAAE,0BAA0B,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAChF,OAAO,MAAM,CAAC,8BAA8B,CAAC,CAAA;IAC/C,CAAC;IACD,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC;QAAE,OAAO,MAAM,CAAC,8BAA8B,CAAC,CAAA;IAC5F,IAAI,IAAI,CAAC,QAAQ,IAAI,KAAK,CAAC,GAAG;QAAE,OAAO,MAAM,CAAC,gCAAgC,CAAC,CAAA;IAE/E,4BAA4B;IAC5B,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IACvC,IAAI,CAAC,QAAQ,EAAE,WAAW;QAAE,OAAO,MAAM,CAAC,oBAAoB,CAAC,CAAA;IAC/D,MAAM,OAAO,GAAG,MAAM,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,YAAY,EAAE,OAAO,CAAC,CAAA;IACrE,IAAI,OAAO,EAAE,KAAK,KAAK,UAAU;QAAE,OAAO,MAAM,CAAC,wBAAwB,CAAC,CAAA;IAC1E,IAAI,OAAO,EAAE,KAAK,KAAK,UAAU;QAAE,OAAO,MAAM,CAAC,uBAAuB,CAAC,CAAA;IACzE,MAAM,mBAAmB,GACvB,cAAc,CAAC,OAAO,CAAC,UAAU,EAAE,IAAI,CAAC,QAAQ,CAAC;QACjD,cAAc,CAAC,OAAO,CAAC,UAAU,EAAE,WAAW,CAAC,CAAA;IACjD,gGAAgG;IAChG,4BAA4B;IAC5B,IACE,CAAC,cAAc,CAAC,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC;QAC1C,CAAC,cAAc,CAAC,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC;QAC1C,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC;QACxC,CAAC,mBAAmB;QACpB,qBAAqB,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,MAAM,GAAG,CAAC,EACnD,CAAC;QACD,OAAO,MAAM,CAAC,wBAAwB,CAAC,CAAA;IACzC,CAAC;IACD,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,oBAAoB,CAAC,CAAA;IAC5F,IAAI,CAAC,GAAG,EAAE,MAAM;QAAE,OAAO,MAAM,CAAC,0BAA0B,CAAC,CAAA;IAC3D,uEAAuE;IACvE,IAAI,GAAG,CAAC,MAAM,KAAK,IAAI,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,WAAW;QAAE,OAAO,MAAM,CAAC,0BAA0B,CAAC,CAAA;IAChG,IAAI,GAAG,CAAC,OAAO,KAAK,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC;QACjE,OAAO,MAAM,CAAC,wBAAwB,CAAC,CAAA;IACzC,CAAC;IAED,sFAAsF;IACtF,IAAI,OAAO,GAAmB,IAAI,CAAA;IAClC,IAAI,KAAK,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;QAChC,MAAM,CAAC,GAAG,WAAW,CAAC,KAAK,CAAC,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE;YAC3D,OAAO,EAAE,MAAM,CAAC,OAAO;YACvB,IAAI;SACL,CAAC,CAAA;QACF,IAAI,CAAC,CAAC,CAAC,EAAE;YAAE,OAAO,CAAC,CAAA;QACnB,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,CAAA;QACzB,IACE,CAAC,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE,CAAC,CAAC,EAAE,IAAI,CAAC,WAAW,CAAC;YAChD,OAAO,CAAC,UAAU,KAAK,IAAI,CAAC,eAAe;YAC3C,CAAC,cAAc,CAAC,OAAO,CAAC,OAAO,EAAE,QAAQ,CAAC,OAAO,CAAC;YAClD,CAAC,cAAc,CAAC,OAAO,CAAC,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,EAChD,CAAC;YACD,OAAO,MAAM,CAAC,gCAAgC,CAAC,CAAA;QACjD,CAAC;QACD,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,kBAAkB,CAC3C,QAAQ,CAAC,OAAO,EAChB,QAAQ,CAAC,gBAAgB,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EACtC,CAAC,CAAC,KAAK,CAAC,SAAS,CAClB,CAAA;QACD,IAAI,CAAC,MAAM;YAAE,OAAO,MAAM,CAAC,2BAA2B,CAAC,CAAA;QACvD,0FAA0F;QAC1F,wFAAwF;QACxF,MAAM,MAAM,GAAG,YAAY,CAAC;YAC1B,OAAO;YACP,OAAO,EAAE;gBACP,YAAY,EAAE,IAAI,CAAC,YAAY;gBAC/B,QAAQ,EAAE,IAAI,CAAC,QAAQ;gBACvB,QAAQ,EAAE,MAAM,CAAC,UAAU;gBAC3B,KAAK,EAAE,IAAI,CAAC,KAAK;gBACjB,QAAQ,EAAE,KAAK,CAAC,MAAM,CAAC,QAAQ;gBAC/B,uFAAuF;gBACvF,8DAA8D;gBAC9D,KAAK,EAAE,KAAK,CAAC,KAAK;aACnB;YACD,KAAK;YACL,YAAY,EAAE,EAAE;YAChB,OAAO,EAAE,KAAK;YACd,GAAG,EAAE,KAAK,CAAC,GAAG;YACd,OAAO,EAAE,MAAM,CAAC,OAAO;SACxB,CAAC,CAAA;QACF,IAAI,MAAM,CAAC,MAAM,KAAK,QAAQ;YAAE,OAAO,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;IAC9D,CAAC;IAED,OAAO;QACL,EAAE,EAAE,IAAI;QACR,aAAa,EAAE,IAAI;QACnB,IAAI;QACJ,MAAM,EAAE,CAAC;QACT,QAAQ;QACR,OAAO;QACP,KAAK;QACL,OAAO;QACP,MAAM;KACP,CAAA;AACH,CAAC"}
|