@avow-finance/sdk 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 +122 -2
- package/dist/agent-entry.d.ts +15 -0
- package/dist/agent-entry.d.ts.map +1 -0
- package/dist/agent-entry.js +11 -0
- package/dist/agent-entry.js.map +1 -0
- package/dist/agent-key.d.ts +34 -0
- package/dist/agent-key.d.ts.map +1 -0
- package/dist/agent-key.js +33 -0
- package/dist/agent-key.js.map +1 -0
- package/dist/agent.d.ts +261 -0
- package/dist/agent.d.ts.map +1 -0
- package/dist/agent.js +493 -0
- package/dist/agent.js.map +1 -0
- package/dist/avow-api.d.ts +78 -0
- package/dist/avow-api.d.ts.map +1 -0
- package/dist/avow-api.js +2 -0
- package/dist/avow-api.js.map +1 -0
- package/dist/contest.d.ts +135 -0
- package/dist/contest.d.ts.map +1 -0
- package/dist/contest.js +186 -0
- package/dist/contest.js.map +1 -0
- package/dist/http.d.ts +161 -0
- package/dist/http.d.ts.map +1 -0
- package/dist/http.js +311 -0
- package/dist/http.js.map +1 -0
- package/dist/index.d.ts +38 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +38 -0
- package/dist/index.js.map +1 -0
- package/dist/job/accept.d.ts +84 -0
- package/dist/job/accept.d.ts.map +1 -0
- package/dist/job/accept.js +136 -0
- package/dist/job/accept.js.map +1 -0
- package/dist/job/customer.d.ts +43 -0
- package/dist/job/customer.d.ts.map +1 -0
- package/dist/job/customer.js +83 -0
- package/dist/job/customer.js.map +1 -0
- package/dist/job/quote.d.ts +34 -0
- package/dist/job/quote.d.ts.map +1 -0
- package/dist/job/quote.js +37 -0
- package/dist/job/quote.js.map +1 -0
- package/dist/lock.d.ts +269 -0
- package/dist/lock.d.ts.map +1 -0
- package/dist/lock.js +283 -0
- package/dist/lock.js.map +1 -0
- package/dist/moderato.d.ts +27 -0
- package/dist/moderato.d.ts.map +1 -0
- package/dist/moderato.js +34 -0
- package/dist/moderato.js.map +1 -0
- package/dist/node/cli.d.ts +3 -0
- package/dist/node/cli.d.ts.map +1 -0
- package/dist/node/cli.js +346 -0
- package/dist/node/cli.js.map +1 -0
- package/dist/node/connect.d.ts +15 -0
- package/dist/node/connect.d.ts.map +1 -0
- package/dist/node/connect.js +91 -0
- package/dist/node/connect.js.map +1 -0
- package/dist/node/eval.d.ts +3 -0
- package/dist/node/eval.d.ts.map +1 -0
- package/dist/node/eval.js +67 -0
- package/dist/node/eval.js.map +1 -0
- package/dist/node/first-run.d.ts +50 -0
- package/dist/node/first-run.d.ts.map +1 -0
- package/dist/node/first-run.js +149 -0
- package/dist/node/first-run.js.map +1 -0
- package/dist/node/job.d.ts +50 -0
- package/dist/node/job.d.ts.map +1 -0
- package/dist/node/job.js +176 -0
- package/dist/node/job.js.map +1 -0
- package/dist/node/mailbox.d.ts +19 -0
- package/dist/node/mailbox.d.ts.map +1 -0
- package/dist/node/mailbox.js +81 -0
- package/dist/node/mailbox.js.map +1 -0
- package/dist/node/mcp.d.ts +74 -0
- package/dist/node/mcp.d.ts.map +1 -0
- package/dist/node/mcp.js +367 -0
- package/dist/node/mcp.js.map +1 -0
- package/dist/node/platform.d.ts +35 -0
- package/dist/node/platform.d.ts.map +1 -0
- package/dist/node/platform.js +102 -0
- package/dist/node/platform.js.map +1 -0
- package/dist/node/runner-session.d.ts +41 -0
- package/dist/node/runner-session.d.ts.map +1 -0
- package/dist/node/runner-session.js +100 -0
- package/dist/node/runner-session.js.map +1 -0
- package/dist/node/runner.d.ts +63 -0
- package/dist/node/runner.d.ts.map +1 -0
- package/dist/node/runner.js +341 -0
- package/dist/node/runner.js.map +1 -0
- package/dist/node/service-child.d.ts +2 -0
- package/dist/node/service-child.d.ts.map +1 -0
- package/dist/node/service-child.js +40 -0
- package/dist/node/service-child.js.map +1 -0
- package/dist/node/service-excerpt.d.ts +21 -0
- package/dist/node/service-excerpt.d.ts.map +1 -0
- package/dist/node/service-excerpt.js +32 -0
- package/dist/node/service-excerpt.js.map +1 -0
- package/dist/node/service-process.d.ts +12 -0
- package/dist/node/service-process.d.ts.map +1 -0
- package/dist/node/service-process.js +132 -0
- package/dist/node/service-process.js.map +1 -0
- package/dist/node/session-input.d.ts +12 -0
- package/dist/node/session-input.d.ts.map +1 -0
- package/dist/node/session-input.js +42 -0
- package/dist/node/session-input.js.map +1 -0
- package/dist/node/session-view.d.ts +20 -0
- package/dist/node/session-view.d.ts.map +1 -0
- package/dist/node/session-view.js +198 -0
- package/dist/node/session-view.js.map +1 -0
- package/dist/node-agent.d.ts +2 -0
- package/dist/node-agent.d.ts.map +1 -0
- package/dist/node-agent.js +6 -0
- package/dist/node-agent.js.map +1 -0
- package/dist/node.d.ts +2 -0
- package/dist/node.d.ts.map +1 -0
- package/dist/node.js +9 -0
- package/dist/node.js.map +1 -0
- package/dist/sandbox/agent.d.ts +187 -0
- package/dist/sandbox/agent.d.ts.map +1 -0
- package/dist/sandbox/agent.js +468 -0
- package/dist/sandbox/agent.js.map +1 -0
- package/dist/sandbox/business-store.d.ts +19 -0
- package/dist/sandbox/business-store.d.ts.map +1 -0
- package/dist/sandbox/business-store.js +19 -0
- package/dist/sandbox/business-store.js.map +1 -0
- package/dist/sandbox/business.d.ts +70 -0
- package/dist/sandbox/business.d.ts.map +1 -0
- package/dist/sandbox/business.js +115 -0
- package/dist/sandbox/business.js.map +1 -0
- package/dist/sandbox/connect.d.ts +64 -0
- package/dist/sandbox/connect.d.ts.map +1 -0
- package/dist/sandbox/connect.js +182 -0
- package/dist/sandbox/connect.js.map +1 -0
- package/dist/sandbox/deployment.d.ts +14 -0
- package/dist/sandbox/deployment.d.ts.map +1 -0
- package/dist/sandbox/deployment.js +38 -0
- package/dist/sandbox/deployment.js.map +1 -0
- package/dist/sandbox/keys.d.ts +45 -0
- package/dist/sandbox/keys.d.ts.map +1 -0
- package/dist/sandbox/keys.js +132 -0
- package/dist/sandbox/keys.js.map +1 -0
- package/dist/sandbox/mailbox.d.ts +90 -0
- package/dist/sandbox/mailbox.d.ts.map +1 -0
- package/dist/sandbox/mailbox.js +400 -0
- package/dist/sandbox/mailbox.js.map +1 -0
- package/dist/sandbox/mandate.d.ts +84 -0
- package/dist/sandbox/mandate.d.ts.map +1 -0
- package/dist/sandbox/mandate.js +107 -0
- package/dist/sandbox/mandate.js.map +1 -0
- package/dist/sandbox/namespace.d.ts +16 -0
- package/dist/sandbox/namespace.d.ts.map +1 -0
- package/dist/sandbox/namespace.js +16 -0
- package/dist/sandbox/namespace.js.map +1 -0
- package/dist/sandbox/session.d.ts +60 -0
- package/dist/sandbox/session.d.ts.map +1 -0
- package/dist/sandbox/session.js +94 -0
- package/dist/sandbox/session.js.map +1 -0
- package/dist/sandbox/setup.d.ts +136 -0
- package/dist/sandbox/setup.d.ts.map +1 -0
- package/dist/sandbox/setup.js +490 -0
- package/dist/sandbox/setup.js.map +1 -0
- package/dist/sandbox/store.d.ts +69 -0
- package/dist/sandbox/store.d.ts.map +1 -0
- package/dist/sandbox/store.js +115 -0
- package/dist/sandbox/store.js.map +1 -0
- package/dist/sandbox/supplier-key.d.ts +73 -0
- package/dist/sandbox/supplier-key.d.ts.map +1 -0
- package/dist/sandbox/supplier-key.js +180 -0
- package/dist/sandbox/supplier-key.js.map +1 -0
- package/dist/sandbox/suppliers.d.ts +7 -0
- package/dist/sandbox/suppliers.d.ts.map +1 -0
- package/dist/sandbox/suppliers.js +29 -0
- package/dist/sandbox/suppliers.js.map +1 -0
- package/dist/sandbox/terms.d.ts +32 -0
- package/dist/sandbox/terms.d.ts.map +1 -0
- package/dist/sandbox/terms.js +58 -0
- package/dist/sandbox/terms.js.map +1 -0
- package/dist/sandbox/vault.d.ts +24 -0
- package/dist/sandbox/vault.d.ts.map +1 -0
- package/dist/sandbox/vault.js +54 -0
- package/dist/sandbox/vault.js.map +1 -0
- package/dist/send.d.ts +122 -0
- package/dist/send.d.ts.map +1 -0
- package/dist/send.js +328 -0
- package/dist/send.js.map +1 -0
- package/dist/service-entry.d.ts +6 -0
- package/dist/service-entry.d.ts.map +1 -0
- package/dist/service-entry.js +6 -0
- package/dist/service-entry.js.map +1 -0
- package/dist/session/anthropic.d.ts +17 -0
- package/dist/session/anthropic.d.ts.map +1 -0
- package/dist/session/anthropic.js +215 -0
- package/dist/session/anthropic.js.map +1 -0
- package/dist/session/charge.d.ts +13 -0
- package/dist/session/charge.d.ts.map +1 -0
- package/dist/session/charge.js +33 -0
- package/dist/session/charge.js.map +1 -0
- package/dist/session/data.d.ts +8 -0
- package/dist/session/data.d.ts.map +1 -0
- package/dist/session/data.js +20 -0
- package/dist/session/data.js.map +1 -0
- package/dist/session/eval.d.ts +41 -0
- package/dist/session/eval.d.ts.map +1 -0
- package/dist/session/eval.js +281 -0
- package/dist/session/eval.js.map +1 -0
- package/dist/session/executor.d.ts +80 -0
- package/dist/session/executor.d.ts.map +1 -0
- package/dist/session/executor.js +381 -0
- package/dist/session/executor.js.map +1 -0
- package/dist/session/fixture-world.d.ts +29 -0
- package/dist/session/fixture-world.d.ts.map +1 -0
- package/dist/session/fixture-world.js +708 -0
- package/dist/session/fixture-world.js.map +1 -0
- package/dist/session/live-world.d.ts +22 -0
- package/dist/session/live-world.d.ts.map +1 -0
- package/dist/session/live-world.js +329 -0
- package/dist/session/live-world.js.map +1 -0
- package/dist/session/ollama.d.ts +29 -0
- package/dist/session/ollama.d.ts.map +1 -0
- package/dist/session/ollama.js +177 -0
- package/dist/session/ollama.js.map +1 -0
- package/dist/session/provider.d.ts +79 -0
- package/dist/session/provider.d.ts.map +1 -0
- package/dist/session/provider.js +19 -0
- package/dist/session/provider.js.map +1 -0
- package/dist/session/scripted.d.ts +45 -0
- package/dist/session/scripted.d.ts.map +1 -0
- package/dist/session/scripted.js +236 -0
- package/dist/session/scripted.js.map +1 -0
- package/dist/session/selection.d.ts +37 -0
- package/dist/session/selection.d.ts.map +1 -0
- package/dist/session/selection.js +104 -0
- package/dist/session/selection.js.map +1 -0
- package/dist/session/service-check.d.ts +48 -0
- package/dist/session/service-check.d.ts.map +1 -0
- package/dist/session/service-check.js +86 -0
- package/dist/session/service-check.js.map +1 -0
- package/dist/session/service.d.ts +128 -0
- package/dist/session/service.d.ts.map +1 -0
- package/dist/session/service.js +150 -0
- package/dist/session/service.js.map +1 -0
- package/dist/session/session.d.ts +95 -0
- package/dist/session/session.d.ts.map +1 -0
- package/dist/session/session.js +312 -0
- package/dist/session/session.js.map +1 -0
- package/dist/session/toolbox.d.ts +69 -0
- package/dist/session/toolbox.d.ts.map +1 -0
- package/dist/session/toolbox.js +391 -0
- package/dist/session/toolbox.js.map +1 -0
- package/dist/session/tools.d.ts +45 -0
- package/dist/session/tools.d.ts.map +1 -0
- package/dist/session/tools.js +137 -0
- package/dist/session/tools.js.map +1 -0
- package/dist/session/world.d.ts +188 -0
- package/dist/session/world.d.ts.map +1 -0
- package/dist/session/world.js +2 -0
- package/dist/session/world.js.map +1 -0
- package/dist/sign.d.ts +19 -0
- package/dist/sign.d.ts.map +1 -0
- package/dist/sign.js +33 -0
- package/dist/sign.js.map +1 -0
- package/dist/supplier.d.ts +41 -0
- package/dist/supplier.d.ts.map +1 -0
- package/dist/supplier.js +57 -0
- package/dist/supplier.js.map +1 -0
- package/package.json +56 -3
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { type ChargeKind, type ContestReason, type ContestStatement, type ContestStatementAnswer, type ReasonCode } from '@avow-finance/spec';
|
|
2
|
+
import { type LockedBacking } from '@avow-finance/verifier';
|
|
3
|
+
import { type Address, type Chain, type Client, type Hex, type TransactionReceipt, type Transport } from 'viem';
|
|
4
|
+
import type { Account as TempoAccount } from 'viem/tempo';
|
|
5
|
+
import type { BusinessRecords } from './avow-api.js';
|
|
6
|
+
import { type Call } from './lock.js';
|
|
7
|
+
import { type OnSent, type SendLimits } from './send.js';
|
|
8
|
+
/**
|
|
9
|
+
* How long, in seconds, a contest sent now may take to land. The root key sends it on an expiring
|
|
10
|
+
* nonce, which viem keeps valid for 25 seconds from when it's prepared, so a contest of a pending
|
|
11
|
+
* charge goes out only while its window stays open that long past the latest block.
|
|
12
|
+
*/
|
|
13
|
+
export declare const CONTEST_SEND_MARGIN = 25n;
|
|
14
|
+
/**
|
|
15
|
+
* Why the lock won't take the business's contest of a commitment in a block up to `landsBy`, by the
|
|
16
|
+
* chain's clock, or null when it will. The lock takes one contest per commitment, of a pending
|
|
17
|
+
* charge until its contest window closes, or of a report Avow hasn't confirmed or referred at any
|
|
18
|
+
* time. `contest` passes the latest block's time plus `CONTEST_SEND_MARGIN`.
|
|
19
|
+
*/
|
|
20
|
+
export declare function contestProblem(held: LockedBacking, landsBy: bigint): ReasonCode | null;
|
|
21
|
+
/** What contesting a charge needs: the business account's root key, its lock and Avow. */
|
|
22
|
+
export interface ContestConfig {
|
|
23
|
+
/** A client for the chain the business's lock is on, with the chain's fee token set. */
|
|
24
|
+
client: Client<Transport, Chain>;
|
|
25
|
+
/** The business account's root key, the one key the lock takes a direct contest from. */
|
|
26
|
+
root: TempoAccount.RootAccount;
|
|
27
|
+
/** The business's lock. */
|
|
28
|
+
lock: Address;
|
|
29
|
+
/** Avow's records the root key gives the statement to, as `httpBusinessRecords` serves them. */
|
|
30
|
+
avow: BusinessRecords;
|
|
31
|
+
/**
|
|
32
|
+
* Sends calls from the root key, which pays its own fee, and resolves with the receipt once they
|
|
33
|
+
* land. By default the key signs locally and the hash is tracked through `sendOwn`, which throws
|
|
34
|
+
* a `SendError` when the transaction fails or its outcome is unknown. A test passes its own.
|
|
35
|
+
*/
|
|
36
|
+
send?: (calls: readonly Call[], onSent: OnSent) => Promise<TransactionReceipt>;
|
|
37
|
+
limits?: SendLimits;
|
|
38
|
+
}
|
|
39
|
+
/** One contest the business makes. */
|
|
40
|
+
export interface ContestRequest {
|
|
41
|
+
commitmentId: Hex;
|
|
42
|
+
reason: ContestReason;
|
|
43
|
+
/** The business's account in its own words, which the statement carries. */
|
|
44
|
+
text: string;
|
|
45
|
+
/**
|
|
46
|
+
* Called with the statement and the contest transaction's hash before its bytes go out, and
|
|
47
|
+
* awaited, so a caller can keep what it needs to settle a run that stops before the end.
|
|
48
|
+
*/
|
|
49
|
+
onSent?: (sent: SentContest) => unknown;
|
|
50
|
+
}
|
|
51
|
+
/** A contest whose transaction is going out, before anyone has seen it land. */
|
|
52
|
+
export interface SentContest {
|
|
53
|
+
statement: ContestStatement;
|
|
54
|
+
hash: Hex;
|
|
55
|
+
/** The first block time at which the transaction can no longer land, or null when it has none. */
|
|
56
|
+
validBefore: bigint | null;
|
|
57
|
+
}
|
|
58
|
+
/** A contest the lock took, with when it paused the charge and how long Avow has to rule. */
|
|
59
|
+
export interface LandedContest {
|
|
60
|
+
statement: ContestStatement;
|
|
61
|
+
statementHash: Hex;
|
|
62
|
+
transactionHash: Hex;
|
|
63
|
+
/** The charge the contested report names, with its amount in base units of the lock's token. */
|
|
64
|
+
charge: {
|
|
65
|
+
kind: ChargeKind;
|
|
66
|
+
amount: bigint;
|
|
67
|
+
};
|
|
68
|
+
/** When the lock paused the charge, which days 30 and 90 count from. */
|
|
69
|
+
pausedAt: bigint;
|
|
70
|
+
/** When Avow's ruling key stops, the pause plus the lock's `rulingKeyEnd`. Avow rules before it. */
|
|
71
|
+
ruleBy: bigint;
|
|
72
|
+
}
|
|
73
|
+
/** Whether Avow recorded the statement, with when, or the error that stopped it. */
|
|
74
|
+
export type StatementPosting = {
|
|
75
|
+
ok: true;
|
|
76
|
+
recordedAt: bigint;
|
|
77
|
+
} | {
|
|
78
|
+
ok: false;
|
|
79
|
+
error: Error;
|
|
80
|
+
};
|
|
81
|
+
/**
|
|
82
|
+
* A contest's outcome. A refusal comes before anything is sent. Once the lock takes the contest,
|
|
83
|
+
* it stands whatever happens to the statement, so the result carries the contest with whether Avow
|
|
84
|
+
* recorded the statement, which `postContestStatement` can give Avow again at any time.
|
|
85
|
+
*/
|
|
86
|
+
export type ContestResult = {
|
|
87
|
+
ok: false;
|
|
88
|
+
reason: ReasonCode;
|
|
89
|
+
} | {
|
|
90
|
+
ok: true;
|
|
91
|
+
contest: LandedContest;
|
|
92
|
+
posted: StatementPosting;
|
|
93
|
+
};
|
|
94
|
+
/**
|
|
95
|
+
* How many times a statement goes to Avow while Avow doesn't see the contest final yet. With the
|
|
96
|
+
* default wait of two seconds between tries, that gives the contest's block about 18 seconds to
|
|
97
|
+
* reach Avow's node and become final, many times what Tempo's finality takes.
|
|
98
|
+
*/
|
|
99
|
+
export declare const STATEMENT_TRIES = 10;
|
|
100
|
+
/**
|
|
101
|
+
* Gives Avow the statement for a contest the lock took, and returns Avow's answer. Avow records a
|
|
102
|
+
* statement only once the contest's block is final, and its node can be a block behind the one
|
|
103
|
+
* that gave the contest's receipt, so while Avow answers that the transaction holds no contest yet,
|
|
104
|
+
* it asks again, up to `STATEMENT_TRIES` times. Any other
|
|
105
|
+
* refusal, or no definite answer, throws an `AvowApiError`. Avow keeps one statement per
|
|
106
|
+
* commitment, so posting the same statement again is always safe.
|
|
107
|
+
*/
|
|
108
|
+
export declare function postContestStatement(avow: BusinessRecords, contest: Pick<LandedContest, 'statement' | 'transactionHash'>, limits?: SendLimits): Promise<ContestStatementAnswer>;
|
|
109
|
+
/**
|
|
110
|
+
* Contests a charge with the business account's root key and gives Avow the statement. It reads
|
|
111
|
+
* the lock first and refuses, sending nothing, a commitment the lock doesn't hold
|
|
112
|
+
* (`chain.reserve_missing`), one already contested, one with no pending charge or standing report,
|
|
113
|
+
* and a pending charge whose contest window closes within `CONTEST_SEND_MARGIN` of the latest
|
|
114
|
+
* block's time, since a contest sent then could land too late. It also refuses a reason that
|
|
115
|
+
* doesn't answer the kind of charge reported and a statement the format doesn't take, since a
|
|
116
|
+
* contest can't be taken back. It throws, sending nothing, when the root key isn't
|
|
117
|
+
* the account that owns the lock.
|
|
118
|
+
*
|
|
119
|
+
* Then it sends the lock's `contest` from the root key, which pays its own fee, signed locally and
|
|
120
|
+
* tracked by its hash, with `onSent` told before the bytes go out. A send that fails or whose
|
|
121
|
+
* outcome is unknown throws the sender's `SendError`. Once the receipt shows the contest landed, it
|
|
122
|
+
* posts the statement to Avow, signed by the root key. The contest stands whether or not that
|
|
123
|
+
* works, so the result carries it either way, with whether Avow recorded the statement.
|
|
124
|
+
*/
|
|
125
|
+
export declare function contest(config: ContestConfig, request: ContestRequest): Promise<ContestResult>;
|
|
126
|
+
/**
|
|
127
|
+
* Reads a contest a successful transaction carried, as `contest` returns it, so a caller that
|
|
128
|
+
* stopped after sending can settle it from the chain. The charge is the one the contested report
|
|
129
|
+
* named, read from the lock as of the contest's block, so a report the supplier filed after
|
|
130
|
+
* withdrawing that one never reads as the charge contested. It returns null when the transaction
|
|
131
|
+
* isn't on the chain, failed, or holds no contest of the statement's commitment from the lock, and
|
|
132
|
+
* throws when the transaction carried a contest with another reason, statement or report.
|
|
133
|
+
*/
|
|
134
|
+
export declare function readLandedContest(config: Pick<ContestConfig, 'client' | 'lock'>, statement: ContestStatement, transactionHash: Hex): Promise<LandedContest | null>;
|
|
135
|
+
//# sourceMappingURL=contest.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contest.d.ts","sourceRoot":"","sources":["../src/contest.ts"],"names":[],"mappings":"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"}
|
package/dist/contest.js
ADDED
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import { answersCharge, CONTEST_REASONS, contestStatementHash, parseContestStatement, } from '@avow-finance/spec';
|
|
2
|
+
import { contestInLogs, LOCK_ABI, readBacking, readContest, } from '@avow-finance/verifier';
|
|
3
|
+
import { isAddressEqual, } from 'viem';
|
|
4
|
+
import { getBlock, readContract } from 'viem/actions';
|
|
5
|
+
import { AvowApiError } from './http.js';
|
|
6
|
+
import { contestCall } from './lock.js';
|
|
7
|
+
import { SEND_LIMITS, sendOwn } from './send.js';
|
|
8
|
+
/**
|
|
9
|
+
* How long, in seconds, a contest sent now may take to land. The root key sends it on an expiring
|
|
10
|
+
* nonce, which viem keeps valid for 25 seconds from when it's prepared, so a contest of a pending
|
|
11
|
+
* charge goes out only while its window stays open that long past the latest block.
|
|
12
|
+
*/
|
|
13
|
+
export const CONTEST_SEND_MARGIN = 25n;
|
|
14
|
+
/**
|
|
15
|
+
* Why the lock won't take the business's contest of a commitment in a block up to `landsBy`, by the
|
|
16
|
+
* chain's clock, or null when it will. The lock takes one contest per commitment, of a pending
|
|
17
|
+
* charge until its contest window closes, or of a report Avow hasn't confirmed or referred at any
|
|
18
|
+
* time. `contest` passes the latest block's time plus `CONTEST_SEND_MARGIN`.
|
|
19
|
+
*/
|
|
20
|
+
export function contestProblem(held, landsBy) {
|
|
21
|
+
// A contest stays on record when the supplier withdraws the report, and a later report pauses
|
|
22
|
+
// at once, so a contested commitment the lock still holds takes no second contest.
|
|
23
|
+
if (held.contested && (held.state === 'paused' || held.state === 'accepted')) {
|
|
24
|
+
return 'contest.already_contested';
|
|
25
|
+
}
|
|
26
|
+
const pending = held.state === 'charge_pending';
|
|
27
|
+
if (!pending && !(held.state === 'accepted' && held.hasReport))
|
|
28
|
+
return 'contest.not_contestable';
|
|
29
|
+
if (pending && landsBy >= held.chargeStart + held.contestWindow)
|
|
30
|
+
return 'contest.window_closed';
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* How many times a statement goes to Avow while Avow doesn't see the contest final yet. With the
|
|
35
|
+
* default wait of two seconds between tries, that gives the contest's block about 18 seconds to
|
|
36
|
+
* reach Avow's node and become final, many times what Tempo's finality takes.
|
|
37
|
+
*/
|
|
38
|
+
export const STATEMENT_TRIES = 10;
|
|
39
|
+
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
40
|
+
/** The latest block's time, which the lock judges a contest window by. */
|
|
41
|
+
async function chainTime(client) {
|
|
42
|
+
return (await getBlock(client, { blockTag: 'latest' })).timestamp;
|
|
43
|
+
}
|
|
44
|
+
/** The lock's `rulingKeyEnd`, which the factory fixed and no call changes. */
|
|
45
|
+
function rulingKeyEnd(client, lock) {
|
|
46
|
+
return readContract(client, { address: lock, abi: LOCK_ABI, functionName: 'rulingKeyEnd' });
|
|
47
|
+
}
|
|
48
|
+
/** The business account that owns the lock, the one account whose root key can contest on it. */
|
|
49
|
+
function lockAccount(client, lock) {
|
|
50
|
+
return readContract(client, { address: lock, abi: LOCK_ABI, functionName: 'account' });
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* The contest a statement made, from the lock's event and the report it named, or a throw when
|
|
54
|
+
* the event isn't the one the statement's contest logs or names another report. The lock logs its
|
|
55
|
+
* event in the transaction that took the contest, so an event that differs means the transaction
|
|
56
|
+
* carried another contest than the statement's.
|
|
57
|
+
*/
|
|
58
|
+
function landedFrom(seen, statement, facts) {
|
|
59
|
+
const statementHash = contestStatementHash(statement);
|
|
60
|
+
const { kind, number, amount } = facts.report;
|
|
61
|
+
if (!seen ||
|
|
62
|
+
!kind ||
|
|
63
|
+
number !== statement.reportNumber ||
|
|
64
|
+
seen.reasonCode !== CONTEST_REASONS[statement.reason].code ||
|
|
65
|
+
seen.statementHash !== statementHash) {
|
|
66
|
+
throw new Error(`${facts.transactionHash} holds no contest of ${statement.commitmentId} with this statement`);
|
|
67
|
+
}
|
|
68
|
+
return {
|
|
69
|
+
statement,
|
|
70
|
+
statementHash,
|
|
71
|
+
transactionHash: facts.transactionHash,
|
|
72
|
+
charge: { kind, amount },
|
|
73
|
+
pausedAt: seen.pausedAt,
|
|
74
|
+
ruleBy: seen.pausedAt + facts.rulingKeyEnd,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Gives Avow the statement for a contest the lock took, and returns Avow's answer. Avow records a
|
|
79
|
+
* statement only once the contest's block is final, and its node can be a block behind the one
|
|
80
|
+
* that gave the contest's receipt, so while Avow answers that the transaction holds no contest yet,
|
|
81
|
+
* it asks again, up to `STATEMENT_TRIES` times. Any other
|
|
82
|
+
* refusal, or no definite answer, throws an `AvowApiError`. Avow keeps one statement per
|
|
83
|
+
* commitment, so posting the same statement again is always safe.
|
|
84
|
+
*/
|
|
85
|
+
export async function postContestStatement(avow, contest, limits = SEND_LIMITS) {
|
|
86
|
+
for (let i = 1;; i++) {
|
|
87
|
+
try {
|
|
88
|
+
return await avow.postContestStatement({
|
|
89
|
+
statement: contest.statement,
|
|
90
|
+
contestedIn: contest.transactionHash,
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
catch (e) {
|
|
94
|
+
const unseen = e instanceof AvowApiError && e.reason === 'contest.not_on_chain';
|
|
95
|
+
if (!unseen || i >= STATEMENT_TRIES)
|
|
96
|
+
throw e;
|
|
97
|
+
await sleep(limits.wait);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Contests a charge with the business account's root key and gives Avow the statement. It reads
|
|
103
|
+
* the lock first and refuses, sending nothing, a commitment the lock doesn't hold
|
|
104
|
+
* (`chain.reserve_missing`), one already contested, one with no pending charge or standing report,
|
|
105
|
+
* and a pending charge whose contest window closes within `CONTEST_SEND_MARGIN` of the latest
|
|
106
|
+
* block's time, since a contest sent then could land too late. It also refuses a reason that
|
|
107
|
+
* doesn't answer the kind of charge reported and a statement the format doesn't take, since a
|
|
108
|
+
* contest can't be taken back. It throws, sending nothing, when the root key isn't
|
|
109
|
+
* the account that owns the lock.
|
|
110
|
+
*
|
|
111
|
+
* Then it sends the lock's `contest` from the root key, which pays its own fee, signed locally and
|
|
112
|
+
* tracked by its hash, with `onSent` told before the bytes go out. A send that fails or whose
|
|
113
|
+
* outcome is unknown throws the sender's `SendError`. Once the receipt shows the contest landed, it
|
|
114
|
+
* posts the statement to Avow, signed by the root key. The contest stands whether or not that
|
|
115
|
+
* works, so the result carries it either way, with whether Avow recorded the statement.
|
|
116
|
+
*/
|
|
117
|
+
export async function contest(config, request) {
|
|
118
|
+
const { client, lock } = config;
|
|
119
|
+
const limits = config.limits ?? SEND_LIMITS;
|
|
120
|
+
const commitmentId = request.commitmentId.toLowerCase();
|
|
121
|
+
const [held, now, keyEnd, account] = await Promise.all([
|
|
122
|
+
readBacking(client, lock, commitmentId, 'buyer'),
|
|
123
|
+
chainTime(client),
|
|
124
|
+
rulingKeyEnd(client, lock),
|
|
125
|
+
lockAccount(client, lock),
|
|
126
|
+
]);
|
|
127
|
+
if (!isAddressEqual(account, config.root.address)) {
|
|
128
|
+
throw new Error(`The lock ${lock} belongs to the account ${account}, so the root key ${config.root.address} can't contest on it`);
|
|
129
|
+
}
|
|
130
|
+
if (!held)
|
|
131
|
+
return { ok: false, reason: 'chain.reserve_missing' };
|
|
132
|
+
const problem = contestProblem(held, now + CONTEST_SEND_MARGIN);
|
|
133
|
+
if (problem)
|
|
134
|
+
return { ok: false, reason: problem };
|
|
135
|
+
if (!held.reportKind || !answersCharge(request.reason, held.reportKind)) {
|
|
136
|
+
return { ok: false, reason: 'contest.reason_not_for_charge' };
|
|
137
|
+
}
|
|
138
|
+
const parsed = parseContestStatement({
|
|
139
|
+
commitmentId,
|
|
140
|
+
side: 'buyer',
|
|
141
|
+
reportNumber: held.reportCount,
|
|
142
|
+
reason: request.reason,
|
|
143
|
+
text: request.text,
|
|
144
|
+
});
|
|
145
|
+
if (!parsed.ok)
|
|
146
|
+
return { ok: false, reason: parsed.reason };
|
|
147
|
+
const statement = parsed.value;
|
|
148
|
+
const send = config.send ??
|
|
149
|
+
((calls, onSent) => sendOwn({ client, account: config.root, calls, onSent, limits }));
|
|
150
|
+
const receipt = await send([contestCall(lock, statement)], (hash, validBefore) => request.onSent?.({ statement, hash, validBefore }));
|
|
151
|
+
// The lock took the contest only while it named the report read above, so that's its charge.
|
|
152
|
+
const landed = landedFrom(contestInLogs(receipt.logs, lock, commitmentId, 'buyer'), statement, {
|
|
153
|
+
transactionHash: receipt.transactionHash,
|
|
154
|
+
report: { number: held.reportCount, kind: held.reportKind, amount: held.reportAmount },
|
|
155
|
+
rulingKeyEnd: keyEnd,
|
|
156
|
+
});
|
|
157
|
+
let posted;
|
|
158
|
+
try {
|
|
159
|
+
const answer = await postContestStatement(config.avow, landed, limits);
|
|
160
|
+
posted = { ok: true, recordedAt: answer.recordedAt };
|
|
161
|
+
}
|
|
162
|
+
catch (e) {
|
|
163
|
+
posted = { ok: false, error: e instanceof Error ? e : new Error(String(e)) };
|
|
164
|
+
}
|
|
165
|
+
return { ok: true, contest: landed, posted };
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Reads a contest a successful transaction carried, as `contest` returns it, so a caller that
|
|
169
|
+
* stopped after sending can settle it from the chain. The charge is the one the contested report
|
|
170
|
+
* named, read from the lock as of the contest's block, so a report the supplier filed after
|
|
171
|
+
* withdrawing that one never reads as the charge contested. It returns null when the transaction
|
|
172
|
+
* isn't on the chain, failed, or holds no contest of the statement's commitment from the lock, and
|
|
173
|
+
* throws when the transaction carried a contest with another reason, statement or report.
|
|
174
|
+
*/
|
|
175
|
+
export async function readLandedContest(config, statement, transactionHash) {
|
|
176
|
+
const { client, lock } = config;
|
|
177
|
+
const { commitmentId, side } = statement;
|
|
178
|
+
const [seen, keyEnd] = await Promise.all([
|
|
179
|
+
readContest(client, lock, commitmentId, side, transactionHash),
|
|
180
|
+
rulingKeyEnd(client, lock),
|
|
181
|
+
]);
|
|
182
|
+
if (!seen)
|
|
183
|
+
return null;
|
|
184
|
+
return landedFrom(seen, statement, { transactionHash, report: seen.report, rulingKeyEnd: keyEnd });
|
|
185
|
+
}
|
|
186
|
+
//# sourceMappingURL=contest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contest.js","sourceRoot":"","sources":["../src/contest.ts"],"names":[],"mappings":"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"}
|
package/dist/http.d.ts
ADDED
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { type ApiRequest, type AvowDomain, type Enrollment, type EnrollmentRequest, type Parsed, type ReasonCode, type RequestKey, type Signed, type SponsorshipRefusal, type SupplierAuthorizationAnswer } from '@avow-finance/spec';
|
|
2
|
+
import type { Address, Hex } from 'viem';
|
|
3
|
+
import type { PrivateKeyAccount } from 'viem/accounts';
|
|
4
|
+
import type { Account as TempoAccount } from 'viem/tempo';
|
|
5
|
+
import type { AgentKey } from './agent.js';
|
|
6
|
+
import type { AvowApi, AvowRecords, BusinessRecords } from './avow-api.js';
|
|
7
|
+
/**
|
|
8
|
+
* Avow's API refused a request, answered with something the client can't use, or gave no definite
|
|
9
|
+
* answer in time. `status` is the HTTP status, 0 when no answer came, and `reason` the reason code
|
|
10
|
+
* Avow gave, or the parser's reason for an answer that doesn't parse. `requestId` names the
|
|
11
|
+
* operation. Sending the same signed bytes again is always safe, since Avow answers an identical
|
|
12
|
+
* repeat without acting again.
|
|
13
|
+
*/
|
|
14
|
+
export declare class AvowApiError extends Error {
|
|
15
|
+
readonly status: number;
|
|
16
|
+
readonly reason: ReasonCode | null;
|
|
17
|
+
readonly requestId: Hex;
|
|
18
|
+
/**
|
|
19
|
+
* Whether Avow answered definitely, with a refusal or an answer the client can't use. When it's
|
|
20
|
+
* false the client gave up with no definite answer, so Avow may still have recorded the request,
|
|
21
|
+
* and a caller shouldn't treat it as refused.
|
|
22
|
+
*/
|
|
23
|
+
readonly definite: boolean;
|
|
24
|
+
/**
|
|
25
|
+
* What Avow's relay added to its refusal, such as when the key can ask again or which budget is
|
|
26
|
+
* spent, or null for any other answer.
|
|
27
|
+
*/
|
|
28
|
+
readonly sponsorship: SponsorshipRefusal | null;
|
|
29
|
+
constructor(message: string, details: {
|
|
30
|
+
status: number;
|
|
31
|
+
reason: ReasonCode | null;
|
|
32
|
+
requestId: Hex;
|
|
33
|
+
definite: boolean;
|
|
34
|
+
sponsorship?: SponsorshipRefusal | null;
|
|
35
|
+
}, options?: {
|
|
36
|
+
cause?: unknown;
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
/** The reason Avow gave somewhere in an error's causes, such as its relay's refusal. */
|
|
40
|
+
export declare function relayReason(error: unknown): ReasonCode | null;
|
|
41
|
+
/** One resend of the same bytes after no definite answer, as `onResend` receives it. */
|
|
42
|
+
export interface AvowResend {
|
|
43
|
+
requestId: Hex;
|
|
44
|
+
/** The last answer's status, or 0 when none came. */
|
|
45
|
+
status: number;
|
|
46
|
+
/** The last answer's reason, when Avow gave one. */
|
|
47
|
+
reason: ReasonCode | null;
|
|
48
|
+
/** What happened to the last attempt. */
|
|
49
|
+
message: string;
|
|
50
|
+
/** Milliseconds until the bytes go again. */
|
|
51
|
+
waitMs: number;
|
|
52
|
+
}
|
|
53
|
+
export interface AvowRequestConfig {
|
|
54
|
+
/**
|
|
55
|
+
* The deployment's origin, such as `https://api.testnet.avow.finance`. It is the audience every
|
|
56
|
+
* request is signed for, so it can't carry a path, query or fragment.
|
|
57
|
+
*/
|
|
58
|
+
baseUrl: string;
|
|
59
|
+
/** The key that signs every request: an agent's through `agentRequestKey`, or a supplier's. */
|
|
60
|
+
key: RequestKey;
|
|
61
|
+
/** Seconds each signed request stays valid, two minutes by default. Avow refuses more than five. */
|
|
62
|
+
requestValidity?: bigint;
|
|
63
|
+
/**
|
|
64
|
+
* Seconds the client keeps sending the same bytes while no definite answer comes, ten minutes by
|
|
65
|
+
* default. It keeps going past the request's expiry, since Avow answers an identical repeat of a
|
|
66
|
+
* request it has recorded, and says `message.expired` about one it never started.
|
|
67
|
+
*/
|
|
68
|
+
retryFor?: bigint;
|
|
69
|
+
/** Milliseconds before the first resend, doubling up to 15 seconds. */
|
|
70
|
+
retryWait?: number;
|
|
71
|
+
/** Milliseconds one attempt may take before it's abandoned and sent again, 30 seconds by default. */
|
|
72
|
+
attemptTimeout?: number;
|
|
73
|
+
/** The clock, in unix seconds. The system clock by default. */
|
|
74
|
+
now?: () => bigint;
|
|
75
|
+
fetch?: typeof fetch;
|
|
76
|
+
/** Receives each signed request, so the signer can keep the record of what it asked Avow. */
|
|
77
|
+
onSigned?: (request: Signed<ApiRequest>) => void;
|
|
78
|
+
/** Hears about each resend before it waits, so a long run of them never goes unseen. */
|
|
79
|
+
onResend?: (resend: AvowResend) => void;
|
|
80
|
+
}
|
|
81
|
+
export interface HttpAvowApiConfig extends AvowRequestConfig {
|
|
82
|
+
/** The chain and lock the agent's mandate names. Every request is signed under this domain. */
|
|
83
|
+
domain: AvowDomain;
|
|
84
|
+
}
|
|
85
|
+
/** One operation for Avow's API. */
|
|
86
|
+
export interface AvowRequest<T> {
|
|
87
|
+
/** The chain and lock the request is signed under. */
|
|
88
|
+
domain: AvowDomain;
|
|
89
|
+
path: string;
|
|
90
|
+
body: unknown;
|
|
91
|
+
/**
|
|
92
|
+
* Parses the JSON body of a 2xx answer, or gives the reason it can't. Avow answers a repeat with
|
|
93
|
+
* the answer it recorded, so an answer this refuses would come back the same, and it's thrown at
|
|
94
|
+
* once with that reason. It gets the digest of the request it answers, which Avow's timestamps
|
|
95
|
+
* name, and the audience that request was signed for.
|
|
96
|
+
*/
|
|
97
|
+
read: (json: unknown, sent: {
|
|
98
|
+
digest: Hex;
|
|
99
|
+
audience: string;
|
|
100
|
+
}) => Parsed<T>;
|
|
101
|
+
}
|
|
102
|
+
/** The agent's access key as a request signer: its own address and its bare signature. */
|
|
103
|
+
export declare function agentRequestKey(key: AgentKey): RequestKey;
|
|
104
|
+
/**
|
|
105
|
+
* The business account's root key as a request signer. Its address is the account's own, and a
|
|
106
|
+
* root key signs bare, so Avow reads the signature as the account's without a keychain envelope.
|
|
107
|
+
*/
|
|
108
|
+
export declare function rootRequestKey(root: TempoAccount.RootAccount): RequestKey;
|
|
109
|
+
/**
|
|
110
|
+
* A supplier's signing key as a request signer, for the requests a supplier signs itself, such as
|
|
111
|
+
* asking Avow for an authorization or quoting the test customer. It's a plain key, so it signs bare.
|
|
112
|
+
*/
|
|
113
|
+
export declare function signingRequestKey(key: PrivateKeyAccount): RequestKey;
|
|
114
|
+
/**
|
|
115
|
+
* Sends operations to Avow's hosted API, each with a fresh request id and signed with `key` for the
|
|
116
|
+
* deployment at `baseUrl`. It sends the same bytes again after no answer, an answer of any status
|
|
117
|
+
* whose body isn't JSON, a 5xx or `request.in_progress`, until Avow answers definitely or
|
|
118
|
+
* `retryFor` runs out. Avow answers with JSON whatever the status, so bytes that aren't JSON never
|
|
119
|
+
* came whole from Avow. Avow answers an identical repeat with its first answer and does nothing
|
|
120
|
+
* again, so a lost answer never turns into a second action. It never follows a redirect, so a
|
|
121
|
+
* signed body goes nowhere but the deployment it was signed for. A refusal, which is any other 4xx
|
|
122
|
+
* with a JSON body, a 2xx answer `read` refuses, or no definite answer in time, throws an
|
|
123
|
+
* `AvowApiError` with the reason.
|
|
124
|
+
*/
|
|
125
|
+
export declare function avowRequests(config: AvowRequestConfig): <T>({ domain, path, body: value, read }: AvowRequest<T>) => Promise<T>;
|
|
126
|
+
/**
|
|
127
|
+
* Avow's hosted API as an `AvowApi`, for an agent whose mandate names `domain`. Each call is one
|
|
128
|
+
* operation sent through `avowRequests`, so a lost answer never turns into a second approval, a
|
|
129
|
+
* second co-signature or a second record. It serves the reserve check, the relay and Avow's records
|
|
130
|
+
* of cancellations and job starts. Each record's answer carries Avow's timestamp, which has to name
|
|
131
|
+
* the digest of the request the agent signed and the time the answer gives. A commitment already
|
|
132
|
+
* cancelled answers with the first cancellation, whose timestamp names the request that carried it,
|
|
133
|
+
* so `cancel` gives the first cancellation's time to every later call too.
|
|
134
|
+
*/
|
|
135
|
+
export declare function httpAvowApi(config: HttpAvowApiConfig): AvowApi & {
|
|
136
|
+
records: AvowRecords;
|
|
137
|
+
};
|
|
138
|
+
/**
|
|
139
|
+
* Avow's hosted API as the records the business account's root key writes to, for the business
|
|
140
|
+
* whose lock `domain` names. Each call is one operation sent through `avowRequests`, signed with
|
|
141
|
+
* `key`, which `rootRequestKey` makes from the root key. A contest statement's answer has to name
|
|
142
|
+
* the hash of the statement sent.
|
|
143
|
+
*/
|
|
144
|
+
export declare function httpBusinessRecords(config: HttpAvowApiConfig): BusinessRecords;
|
|
145
|
+
/**
|
|
146
|
+
* Enrolls an agent with Avow once its key is on the chain with the mandate's hash. The agent signs
|
|
147
|
+
* the request with that key, under the mandate's chain and lock, and gets back what Avow recorded.
|
|
148
|
+
*/
|
|
149
|
+
export declare function enrollAgent(config: AvowRequestConfig, enrollment: EnrollmentRequest): Promise<Enrollment>;
|
|
150
|
+
/**
|
|
151
|
+
* Asks Avow for a fresh authorization for a commitment's reserve, signed with the supplier's
|
|
152
|
+
* signing key under the buyer's lock. Avow answers with its authorization, the approval the reserve
|
|
153
|
+
* was funded under and the buyer's mandate, which the supplier's verifier checks before it accepts,
|
|
154
|
+
* or with the reason it signed none, such as a reserve not funded yet.
|
|
155
|
+
*/
|
|
156
|
+
export declare function requestSupplierAuthorization(config: AvowRequestConfig, commitment: {
|
|
157
|
+
chainId: number;
|
|
158
|
+
lock: Address;
|
|
159
|
+
commitmentId: Hex;
|
|
160
|
+
}): Promise<SupplierAuthorizationAnswer>;
|
|
161
|
+
//# sourceMappingURL=http.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,UAAU,EACf,KAAK,UAAU,EAGf,KAAK,UAAU,EACf,KAAK,iBAAiB,EAItB,KAAK,MAAM,EAWX,KAAK,UAAU,EACf,KAAK,UAAU,EACf,KAAK,MAAM,EACX,KAAK,kBAAkB,EACvB,KAAK,2BAA2B,EAEjC,MAAM,oBAAoB,CAAA;AAC3B,OAAO,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,MAAM,CAAA;AACxC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAA;AACtD,OAAO,KAAK,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,YAAY,CAAA;AACzD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAC1C,OAAO,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAE1E;;;;;;GAMG;AACH,qBAAa,YAAa,SAAQ,KAAK;IACrC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,CAAA;IAClC,QAAQ,CAAC,SAAS,EAAE,GAAG,CAAA;IACvB;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAA;IAC1B;;;OAGG;IACH,QAAQ,CAAC,WAAW,EAAE,kBAAkB,GAAG,IAAI,CAAA;IAE/C,YACE,OAAO,EAAE,MAAM,EACf,OAAO,EAAE;QACP,MAAM,EAAE,MAAM,CAAA;QACd,MAAM,EAAE,UAAU,GAAG,IAAI,CAAA;QACzB,SAAS,EAAE,GAAG,CAAA;QACd,QAAQ,EAAE,OAAO,CAAA;QACjB,WAAW,CAAC,EAAE,kBAAkB,GAAG,IAAI,CAAA;KACxC,EACD,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,EAS9B;CACF;AAED,wFAAwF;AACxF,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,UAAU,GAAG,IAAI,CAO7D;AAED,wFAAwF;AACxF,MAAM,WAAW,UAAU;IACzB,SAAS,EAAE,GAAG,CAAA;IACd,qDAAqD;IACrD,MAAM,EAAE,MAAM,CAAA;IACd,oDAAoD;IACpD,MAAM,EAAE,UAAU,GAAG,IAAI,CAAA;IACzB,yCAAyC;IACzC,OAAO,EAAE,MAAM,CAAA;IACf,6CAA6C;IAC7C,MAAM,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,iBAAiB;IAChC;;;OAGG;IACH,OAAO,EAAE,MAAM,CAAA;IACf,+FAA+F;IAC/F,GAAG,EAAE,UAAU,CAAA;IACf,oGAAoG;IACpG,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,uEAAuE;IACvE,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,qGAAqG;IACrG,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,+DAA+D;IAC/D,GAAG,CAAC,EAAE,MAAM,MAAM,CAAA;IAClB,KAAK,CAAC,EAAE,OAAO,KAAK,CAAA;IACpB,6FAA6F;IAC7F,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,UAAU,CAAC,KAAK,IAAI,CAAA;IAChD,wFAAwF;IACxF,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,IAAI,CAAA;CACxC;AAED,MAAM,WAAW,iBAAkB,SAAQ,iBAAiB;IAC1D,+FAA+F;IAC/F,MAAM,EAAE,UAAU,CAAA;CACnB;AAED,oCAAoC;AACpC,MAAM,WAAW,WAAW,CAAC,CAAC;IAC5B,sDAAsD;IACtD,MAAM,EAAE,UAAU,CAAA;IAClB,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,OAAO,CAAA;IACb;;;;;OAKG;IACH,IAAI,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE;QAAE,MAAM,EAAE,GAAG,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,KAAK,MAAM,CAAC,CAAC,CAAC,CAAA;CAC5E;AAED,0FAA0F;AAC1F,wBAAgB,eAAe,CAAC,GAAG,EAAE,QAAQ,GAAG,UAAU,CAKzD;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,YAAY,CAAC,WAAW,GAAG,UAAU,CAEzE;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,iBAAiB,GAAG,UAAU,CAEpE;AA8BD;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,iBAAiB,IAazB,CAAC,uCAAuC,WAAW,CAAC,CAAC,CAAC,KAAG,OAAO,CAAC,CAAC,CAAC,CAmF/F;AAMD;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,GAAG;IAAE,OAAO,EAAE,WAAW,CAAA;CAAE,CA4DzF;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,iBAAiB,GAAG,eAAe,CAe9E;AAED;;;GAGG;AACH,wBAAgB,WAAW,CACzB,MAAM,EAAE,iBAAiB,EACzB,UAAU,EAAE,iBAAiB,GAC5B,OAAO,CAAC,UAAU,CAAC,CAOrB;AAED;;;;;GAKG;AACH,wBAAgB,4BAA4B,CAC1C,MAAM,EAAE,iBAAiB,EACzB,UAAU,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,OAAO,CAAC;IAAC,YAAY,EAAE,GAAG,CAAA;CAAE,GAChE,OAAO,CAAC,2BAA2B,CAAC,CAQtC"}
|