web3-tools-mcp 2.0.1 → 3.0.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/CHANGELOG.md +117 -0
- package/README.md +5 -0
- package/dist/anvil.d.ts +17 -19
- package/dist/anvil.d.ts.map +1 -1
- package/dist/anvil.js +124 -228
- package/dist/anvil.js.map +1 -1
- package/dist/chains.d.ts +9 -1
- package/dist/chains.d.ts.map +1 -1
- package/dist/chains.js +11 -2
- package/dist/chains.js.map +1 -1
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js.map +1 -1
- package/dist/context.d.ts +22 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +24 -0
- package/dist/context.js.map +1 -0
- package/dist/hosted.d.ts +12 -0
- package/dist/hosted.d.ts.map +1 -0
- package/dist/hosted.js +12 -0
- package/dist/hosted.js.map +1 -0
- package/dist/http-server.d.ts +13 -0
- package/dist/http-server.d.ts.map +1 -1
- package/dist/http-server.js +13 -4
- package/dist/http-server.js.map +1 -1
- package/dist/index.js +19 -15
- package/dist/index.js.map +1 -1
- package/dist/lib.d.ts +24 -0
- package/dist/lib.d.ts.map +1 -0
- package/dist/lib.js +23 -0
- package/dist/lib.js.map +1 -0
- package/dist/log.d.ts +16 -0
- package/dist/log.d.ts.map +1 -0
- package/dist/log.js +20 -0
- package/dist/log.js.map +1 -0
- package/dist/mcp-server.d.ts +4 -0
- package/dist/mcp-server.d.ts.map +1 -0
- package/dist/mcp-server.js +43 -0
- package/dist/mcp-server.js.map +1 -0
- package/dist/oauth.d.ts +41 -6
- package/dist/oauth.d.ts.map +1 -1
- package/dist/oauth.js +75 -41
- package/dist/oauth.js.map +1 -1
- package/dist/preview.d.ts +7 -0
- package/dist/preview.d.ts.map +1 -1
- package/dist/preview.js +14 -2
- package/dist/preview.js.map +1 -1
- package/dist/signing-requests.d.ts +81 -0
- package/dist/signing-requests.d.ts.map +1 -0
- package/dist/signing-requests.js +138 -0
- package/dist/signing-requests.js.map +1 -0
- package/dist/tools/index.d.ts +27 -1
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +37 -15
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/{advanced.d.ts → read/advanced.d.ts} +30 -26
- package/dist/tools/read/advanced.d.ts.map +1 -0
- package/dist/tools/{advanced.js → read/advanced.js} +10 -10
- package/dist/tools/read/advanced.js.map +1 -0
- package/dist/tools/{balance.d.ts → read/balance.d.ts} +8 -7
- package/dist/tools/read/balance.d.ts.map +1 -0
- package/dist/tools/{balance.js → read/balance.js} +2 -2
- package/dist/tools/read/balance.js.map +1 -0
- package/dist/tools/{contract-info.d.ts → read/contract-info.d.ts} +18 -15
- package/dist/tools/read/contract-info.d.ts.map +1 -0
- package/dist/tools/{contract-info.js → read/contract-info.js} +2 -2
- package/dist/tools/read/contract-info.js.map +1 -0
- package/dist/tools/{contract.d.ts → read/contract.d.ts} +14 -12
- package/dist/tools/read/contract.d.ts.map +1 -0
- package/dist/tools/{contract.js → read/contract.js} +2 -2
- package/dist/tools/read/contract.js.map +1 -0
- package/dist/tools/{ens.d.ts → read/ens.d.ts} +30 -25
- package/dist/tools/read/ens.d.ts.map +1 -0
- package/dist/tools/{ens.js → read/ens.js} +2 -2
- package/dist/tools/read/ens.js.map +1 -0
- package/dist/tools/read/gas.d.ts +171 -0
- package/dist/tools/read/gas.d.ts.map +1 -0
- package/dist/tools/read/gas.js +368 -0
- package/dist/tools/read/gas.js.map +1 -0
- package/dist/tools/{logs.d.ts → read/logs.d.ts} +6 -5
- package/dist/tools/read/logs.d.ts.map +1 -0
- package/dist/tools/{logs.js → read/logs.js} +2 -2
- package/dist/tools/read/logs.js.map +1 -0
- package/dist/tools/{signatures.d.ts → read/signatures.d.ts} +8 -4
- package/dist/tools/read/signatures.d.ts.map +1 -0
- package/dist/tools/{signatures.js → read/signatures.js} +1 -1
- package/dist/tools/read/signatures.js.map +1 -0
- package/dist/tools/read/signing.d.ts +27 -0
- package/dist/tools/read/signing.d.ts.map +1 -0
- package/dist/tools/read/signing.js +75 -0
- package/dist/tools/read/signing.js.map +1 -0
- package/dist/tools/sign/errors.d.ts +9 -0
- package/dist/tools/sign/errors.d.ts.map +1 -0
- package/dist/tools/sign/errors.js +29 -0
- package/dist/tools/sign/errors.js.map +1 -0
- package/dist/tools/{transactions.d.ts → sign/transactions.d.ts} +48 -62
- package/dist/tools/sign/transactions.d.ts.map +1 -0
- package/dist/tools/sign/transactions.js +316 -0
- package/dist/tools/sign/transactions.js.map +1 -0
- package/dist/tools/sign/wallet.d.ts +50 -0
- package/dist/tools/sign/wallet.d.ts.map +1 -0
- package/dist/tools/sign/wallet.js +180 -0
- package/dist/tools/sign/wallet.js.map +1 -0
- package/dist/utils.d.ts +5 -2
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +5 -2
- package/dist/utils.js.map +1 -1
- package/dist/wallet-client.d.ts +33 -4
- package/dist/wallet-client.d.ts.map +1 -1
- package/dist/wallet-client.js +90 -24
- package/dist/wallet-client.js.map +1 -1
- package/dist/walletconnect.d.ts +111 -13
- package/dist/walletconnect.d.ts.map +1 -1
- package/dist/walletconnect.js +248 -68
- package/dist/walletconnect.js.map +1 -1
- package/package.json +10 -4
- package/src/anvil.ts +150 -271
- package/src/chains.ts +14 -2
- package/src/client.ts +0 -1
- package/src/context.ts +27 -0
- package/src/hosted.ts +11 -0
- package/src/http-server.ts +30 -5
- package/src/index.ts +19 -16
- package/src/lib.ts +24 -0
- package/src/log.ts +25 -0
- package/src/mcp-server.ts +47 -0
- package/src/oauth.ts +98 -45
- package/src/preview.ts +21 -2
- package/src/signing-requests.ts +198 -0
- package/src/tools/index.ts +67 -16
- package/src/tools/{advanced.ts → read/advanced.ts} +13 -11
- package/src/tools/{balance.ts → read/balance.ts} +3 -3
- package/src/tools/{contract-info.ts → read/contract-info.ts} +3 -3
- package/src/tools/{contract.ts → read/contract.ts} +3 -3
- package/src/tools/{ens.ts → read/ens.ts} +3 -3
- package/src/tools/read/gas.ts +480 -0
- package/src/tools/{logs.ts → read/logs.ts} +3 -3
- package/src/tools/{signatures.ts → read/signatures.ts} +2 -2
- package/src/tools/read/signing.ts +86 -0
- package/src/tools/sign/errors.ts +28 -0
- package/src/tools/sign/transactions.ts +428 -0
- package/src/tools/sign/wallet.ts +216 -0
- package/src/utils.ts +5 -2
- package/src/wallet-client.ts +91 -22
- package/src/walletconnect.ts +286 -66
- package/dist/tools/advanced.d.ts.map +0 -1
- package/dist/tools/advanced.js.map +0 -1
- package/dist/tools/balance.d.ts.map +0 -1
- package/dist/tools/balance.js.map +0 -1
- package/dist/tools/contract-info.d.ts.map +0 -1
- package/dist/tools/contract-info.js.map +0 -1
- package/dist/tools/contract.d.ts.map +0 -1
- package/dist/tools/contract.js.map +0 -1
- package/dist/tools/ens.d.ts.map +0 -1
- package/dist/tools/ens.js.map +0 -1
- package/dist/tools/gas.d.ts +0 -99
- package/dist/tools/gas.d.ts.map +0 -1
- package/dist/tools/gas.js +0 -181
- package/dist/tools/gas.js.map +0 -1
- package/dist/tools/logs.d.ts.map +0 -1
- package/dist/tools/logs.js.map +0 -1
- package/dist/tools/signatures.d.ts.map +0 -1
- package/dist/tools/signatures.js.map +0 -1
- package/dist/tools/transactions.d.ts.map +0 -1
- package/dist/tools/transactions.js +0 -361
- package/dist/tools/transactions.js.map +0 -1
- package/src/tools/gas.ts +0 -219
- package/src/tools/transactions.ts +0 -452
package/dist/oauth.d.ts
CHANGED
|
@@ -3,26 +3,61 @@ import type { AuthorizationParams, OAuthServerProvider } from '@modelcontextprot
|
|
|
3
3
|
import type { AuthInfo } from '@modelcontextprotocol/sdk/server/auth/types.js';
|
|
4
4
|
import type { OAuthClientInformationFull, OAuthTokens } from '@modelcontextprotocol/sdk/shared/auth.js';
|
|
5
5
|
import type { Response } from 'express';
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
/**
|
|
7
|
+
* How a deployment decides who is at the authorize screen.
|
|
8
|
+
*
|
|
9
|
+
* Deliberately free of any type from the MCP SDK, a chain library, or this package: an
|
|
10
|
+
* implementation renders a page and reads back a form, and everything about *how* somebody
|
|
11
|
+
* proves who they are — a shared token, a wallet signature, a company SSO — stays outside.
|
|
12
|
+
* Returning an address makes the issued token that person's; returning none authenticates
|
|
13
|
+
* the deployment rather than anybody in particular.
|
|
14
|
+
*/
|
|
15
|
+
export interface Login {
|
|
16
|
+
/** The page served at GET /authorize. `hidden` must be placed inside its form. */
|
|
17
|
+
page(hidden: string, error?: string): string | Promise<string>;
|
|
18
|
+
/** Reads the posted form. An `error` re-renders the page; an `address` names the person. */
|
|
19
|
+
identify(form: Record<string, string>): Promise<{
|
|
20
|
+
address?: string;
|
|
21
|
+
error?: string;
|
|
22
|
+
}>;
|
|
23
|
+
/**
|
|
24
|
+
* Form fields this login owns. They are kept out of the hidden inputs replayed into the
|
|
25
|
+
* page, so a credential can never be echoed back into the HTML.
|
|
26
|
+
*/
|
|
27
|
+
owns?: string[];
|
|
28
|
+
}
|
|
29
|
+
/** The default: one shared credential, so a self-hoster needs no identity provider. */
|
|
30
|
+
export declare function tokenLogin(accessToken: string): Login;
|
|
31
|
+
export declare class OAuthProvider implements OAuthServerProvider {
|
|
32
|
+
private login;
|
|
33
|
+
private staticToken?;
|
|
8
34
|
private store;
|
|
9
|
-
|
|
35
|
+
/**
|
|
36
|
+
* `staticToken` is accepted verbatim in an Authorization header, for clients that can send
|
|
37
|
+
* one and skip the flow entirely. It names no person, so it carries no identity.
|
|
38
|
+
*/
|
|
39
|
+
constructor(login: Login, staticToken?: string | undefined);
|
|
10
40
|
get clientsStore(): OAuthRegisteredClientsStore;
|
|
11
41
|
/**
|
|
12
|
-
* GET renders the
|
|
13
|
-
* both here keeps the whole login inside the SDK's authorize
|
|
42
|
+
* GET renders the login; POST hands the form to it and, if it names somebody, redirects
|
|
43
|
+
* back with a code. Handling both here keeps the whole login inside the SDK's authorize
|
|
44
|
+
* route, which is the only place the client will follow a redirect from.
|
|
14
45
|
*/
|
|
15
46
|
authorize(client: OAuthClientInformationFull, params: AuthorizationParams, res: Response): Promise<void>;
|
|
16
47
|
challengeForAuthorizationCode(_client: OAuthClientInformationFull, authorizationCode: string): Promise<string>;
|
|
17
48
|
exchangeAuthorizationCode(client: OAuthClientInformationFull, authorizationCode: string): Promise<OAuthTokens>;
|
|
18
49
|
exchangeRefreshToken(client: OAuthClientInformationFull, refreshToken: string, scopes?: string[]): Promise<OAuthTokens>;
|
|
19
50
|
private issue;
|
|
20
|
-
/** Accepts an issued token, or
|
|
51
|
+
/** Accepts an issued token, or the static one so a client that can send a header still works. */
|
|
21
52
|
verifyAccessToken(token: string): Promise<AuthInfo>;
|
|
22
53
|
revokeToken(_client: OAuthClientInformationFull, request: {
|
|
23
54
|
token: string;
|
|
24
55
|
}): Promise<void>;
|
|
25
56
|
}
|
|
57
|
+
/** One shared credential, which is all a self-hosted server needs. */
|
|
58
|
+
export declare class SingleUserOAuthProvider extends OAuthProvider {
|
|
59
|
+
constructor(accessToken: string);
|
|
60
|
+
}
|
|
26
61
|
/** PKCE helper, used by the tests to drive the flow the way a real client would. */
|
|
27
62
|
export declare function pkce(): {
|
|
28
63
|
verifier: string;
|
package/dist/oauth.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oauth.d.ts","sourceRoot":"","sources":["../src/oauth.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,kDAAkD,CAAA;AAEnG,OAAO,KAAK,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,mDAAmD,CAAA;AACjH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gDAAgD,CAAA;AAC9E,OAAO,KAAK,EAAE,0BAA0B,EAAE,WAAW,EAAE,MAAM,0CAA0C,CAAA;AACvG,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;
|
|
1
|
+
{"version":3,"file":"oauth.d.ts","sourceRoot":"","sources":["../src/oauth.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,kDAAkD,CAAA;AAEnG,OAAO,KAAK,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,mDAAmD,CAAA;AACjH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gDAAgD,CAAA;AAC9E,OAAO,KAAK,EAAE,0BAA0B,EAAE,WAAW,EAAE,MAAM,0CAA0C,CAAA;AACvG,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAuFvC;;;;;;;;GAQG;AACH,MAAM,WAAW,KAAK;IACpB,kFAAkF;IAClF,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;IAC9D,4FAA4F;IAC5F,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC;QAAE,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IACrF;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,EAAE,CAAA;CAChB;AAcD,uFAAuF;AACvF,wBAAgB,UAAU,CAAC,WAAW,EAAE,MAAM,GAAG,KAAK,CAuBrD;AAED,qBAAa,aAAc,YAAW,mBAAmB;IAQrD,OAAO,CAAC,KAAK;IACb,OAAO,CAAC,WAAW,CAAC;IARtB,OAAO,CAAC,KAAK,CAAc;IAE3B;;;OAGG;gBAEO,KAAK,EAAE,KAAK,EACZ,WAAW,CAAC,EAAE,MAAM,YAAA;IAG9B,IAAI,YAAY,IAAI,2BAA2B,CAkB9C;IAED;;;;OAIG;IACG,SAAS,CAAC,MAAM,EAAE,0BAA0B,EAAE,MAAM,EAAE,mBAAmB,EAAE,GAAG,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IA0CxG,6BAA6B,CAAC,OAAO,EAAE,0BAA0B,EAAE,iBAAiB,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAM9G,yBAAyB,CAAC,MAAM,EAAE,0BAA0B,EAAE,iBAAiB,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAU9G,oBAAoB,CAAC,MAAM,EAAE,0BAA0B,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,WAAW,CAAC;YAU/G,KAAK;IAiBnB,iGAAiG;IAC3F,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC;IA0BnD,WAAW,CAAC,OAAO,EAAE,0BAA0B,EAAE,OAAO,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;CAIlG;AAED,sEAAsE;AACtE,qBAAa,uBAAwB,SAAQ,aAAa;gBAC5C,WAAW,EAAE,MAAM;CAGhC;AAED,oFAAoF;AACpF,wBAAgB,IAAI,IAAI;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAI9D"}
|
package/dist/oauth.js
CHANGED
|
@@ -65,17 +65,7 @@ function constantTimeEquals(a, b) {
|
|
|
65
65
|
const right = Buffer.from(b);
|
|
66
66
|
return left.length === right.length && timingSafeEqual(left, right);
|
|
67
67
|
}
|
|
68
|
-
|
|
69
|
-
// The SDK's authorize handler reads its parameters from the body on POST, so the form
|
|
70
|
-
// has to carry the whole authorization request back, not just the token.
|
|
71
|
-
const hidden = Object.entries(params.fields)
|
|
72
|
-
.map(([name, value]) => `<input type="hidden" name="${escapeHtml(name)}" value="${escapeHtml(value)}">`)
|
|
73
|
-
.join('\n ');
|
|
74
|
-
return `<!doctype html>
|
|
75
|
-
<meta charset="utf-8">
|
|
76
|
-
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
77
|
-
<title>Connect to web3-tools-mcp</title>
|
|
78
|
-
<style>
|
|
68
|
+
const PAGE_STYLE = `
|
|
79
69
|
:root { color-scheme: light dark; }
|
|
80
70
|
body { font: 15px/1.5 -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; max-width: 26rem;
|
|
81
71
|
margin: 12vh auto; padding: 0 1.25rem; }
|
|
@@ -85,22 +75,44 @@ function loginPage(params) {
|
|
|
85
75
|
box-sizing: border-box; }
|
|
86
76
|
input { border: 1px solid #ccd; font-family: ui-monospace, monospace; }
|
|
87
77
|
button { margin-top: .75rem; border: 0; background: #3856d6; color: #fff; font-weight: 600; }
|
|
88
|
-
.error { color: #b3251d; font-weight: 600; }
|
|
78
|
+
.error { color: #b3251d; font-weight: 600; }`;
|
|
79
|
+
/** The default: one shared credential, so a self-hoster needs no identity provider. */
|
|
80
|
+
export function tokenLogin(accessToken) {
|
|
81
|
+
return {
|
|
82
|
+
owns: ['token'],
|
|
83
|
+
page: (hidden, error) => `<!doctype html>
|
|
84
|
+
<meta charset="utf-8">
|
|
85
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
86
|
+
<title>Connect to web3-tools-mcp</title>
|
|
87
|
+
<style>${PAGE_STYLE}
|
|
89
88
|
</style>
|
|
90
89
|
<h1>Connect to web3-tools-mcp</h1>
|
|
91
90
|
<p>Paste this server's access token to authorise the client.</p>
|
|
92
|
-
${
|
|
91
|
+
${error ? `<p class="error">${error}</p>` : ''}
|
|
93
92
|
<form method="post">
|
|
94
93
|
${hidden}
|
|
95
94
|
<input name="token" type="password" placeholder="MCP_TOKEN" autocomplete="off" autofocus>
|
|
96
95
|
<button type="submit">Authorise</button>
|
|
97
|
-
</form
|
|
96
|
+
</form>`,
|
|
97
|
+
async identify(form) {
|
|
98
|
+
if (!constantTimeEquals(form.token ?? '', accessToken))
|
|
99
|
+
return { error: 'That token was not accepted.' };
|
|
100
|
+
// No address: this authenticates the deployment, not a person.
|
|
101
|
+
return {};
|
|
102
|
+
}
|
|
103
|
+
};
|
|
98
104
|
}
|
|
99
|
-
export class
|
|
100
|
-
|
|
105
|
+
export class OAuthProvider {
|
|
106
|
+
login;
|
|
107
|
+
staticToken;
|
|
101
108
|
store = new Store();
|
|
102
|
-
|
|
103
|
-
|
|
109
|
+
/**
|
|
110
|
+
* `staticToken` is accepted verbatim in an Authorization header, for clients that can send
|
|
111
|
+
* one and skip the flow entirely. It names no person, so it carries no identity.
|
|
112
|
+
*/
|
|
113
|
+
constructor(login, staticToken) {
|
|
114
|
+
this.login = login;
|
|
115
|
+
this.staticToken = staticToken;
|
|
104
116
|
}
|
|
105
117
|
get clientsStore() {
|
|
106
118
|
const store = this.store;
|
|
@@ -122,26 +134,32 @@ export class SingleUserOAuthProvider {
|
|
|
122
134
|
};
|
|
123
135
|
}
|
|
124
136
|
/**
|
|
125
|
-
* GET renders the
|
|
126
|
-
* both here keeps the whole login inside the SDK's authorize
|
|
137
|
+
* GET renders the login; POST hands the form to it and, if it names somebody, redirects
|
|
138
|
+
* back with a code. Handling both here keeps the whole login inside the SDK's authorize
|
|
139
|
+
* route, which is the only place the client will follow a redirect from.
|
|
127
140
|
*/
|
|
128
141
|
async authorize(client, params, res) {
|
|
129
142
|
const request = res.req;
|
|
130
|
-
const
|
|
131
|
-
//
|
|
132
|
-
//
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
143
|
+
const form = { ...request.query, ...request.body };
|
|
144
|
+
// The SDK's authorize handler reads its parameters from the body on POST, so the form
|
|
145
|
+
// has to carry the whole authorization request back — minus whatever the login owns,
|
|
146
|
+
// which would mean echoing a credential into the HTML.
|
|
147
|
+
const owned = new Set(this.login.owns ?? []);
|
|
148
|
+
const hidden = Object.entries(form)
|
|
149
|
+
.filter(([name, value]) => !owned.has(name) && typeof value === 'string')
|
|
150
|
+
.map(([name, value]) => `<input type="hidden" name="${escapeHtml(name)}" value="${escapeHtml(value)}">`)
|
|
151
|
+
.join('\n ');
|
|
152
|
+
const render = async (status, error) => {
|
|
139
153
|
res
|
|
140
|
-
.status(
|
|
154
|
+
.status(status)
|
|
141
155
|
.setHeader('content-type', 'text/html; charset=utf-8')
|
|
142
|
-
.send(
|
|
143
|
-
|
|
144
|
-
|
|
156
|
+
.send(await this.login.page(hidden, error ? escapeHtml(error) : undefined));
|
|
157
|
+
};
|
|
158
|
+
if (request.method !== 'POST')
|
|
159
|
+
return render(200);
|
|
160
|
+
const identified = await this.login.identify(form);
|
|
161
|
+
if (identified.error)
|
|
162
|
+
return render(401, identified.error);
|
|
145
163
|
const code = randomBytes(24).toString('hex');
|
|
146
164
|
await this.store.set(`code:${code}`, {
|
|
147
165
|
clientId: client.client_id,
|
|
@@ -149,6 +167,7 @@ export class SingleUserOAuthProvider {
|
|
|
149
167
|
redirectUri: params.redirectUri,
|
|
150
168
|
resource: params.resource?.href,
|
|
151
169
|
scopes: params.scopes ?? [],
|
|
170
|
+
address: identified.address,
|
|
152
171
|
expiresAt: Date.now() + CODE_TTL
|
|
153
172
|
});
|
|
154
173
|
const redirect = new URL(params.redirectUri);
|
|
@@ -171,7 +190,7 @@ export class SingleUserOAuthProvider {
|
|
|
171
190
|
throw new Error('Authorization code was issued to a different client');
|
|
172
191
|
// One use only: a replayed code must not mint a second token.
|
|
173
192
|
await this.store.remove(`code:${authorizationCode}`);
|
|
174
|
-
return this.issue(client.client_id, stored.scopes);
|
|
193
|
+
return this.issue(client.client_id, stored.scopes, stored.address);
|
|
175
194
|
}
|
|
176
195
|
async exchangeRefreshToken(client, refreshToken, scopes) {
|
|
177
196
|
const stored = await this.store.get(`refresh:${refreshToken}`);
|
|
@@ -180,14 +199,15 @@ export class SingleUserOAuthProvider {
|
|
|
180
199
|
if (stored.clientId !== client.client_id)
|
|
181
200
|
throw new Error('Refresh token was issued to a different client');
|
|
182
201
|
await this.store.remove(`refresh:${refreshToken}`);
|
|
183
|
-
|
|
202
|
+
// The refreshed token stays the same person's: a refresh proves possession, not identity.
|
|
203
|
+
return this.issue(client.client_id, scopes ?? stored.scopes, stored.address);
|
|
184
204
|
}
|
|
185
|
-
async issue(clientId, scopes) {
|
|
205
|
+
async issue(clientId, scopes, address) {
|
|
186
206
|
const accessToken = randomBytes(32).toString('hex');
|
|
187
207
|
const refreshToken = randomBytes(32).toString('hex');
|
|
188
208
|
const expiresAt = Math.floor(Date.now() / 1000) + TOKEN_TTL;
|
|
189
|
-
await this.store.set(`token:${accessToken}`, { clientId, scopes, expiresAt });
|
|
190
|
-
await this.store.set(`refresh:${refreshToken}`, { clientId, scopes, expiresAt });
|
|
209
|
+
await this.store.set(`token:${accessToken}`, { clientId, scopes, address, expiresAt });
|
|
210
|
+
await this.store.set(`refresh:${refreshToken}`, { clientId, scopes, address, expiresAt });
|
|
191
211
|
return {
|
|
192
212
|
access_token: accessToken,
|
|
193
213
|
token_type: 'Bearer',
|
|
@@ -196,9 +216,9 @@ export class SingleUserOAuthProvider {
|
|
|
196
216
|
scope: scopes.join(' ')
|
|
197
217
|
};
|
|
198
218
|
}
|
|
199
|
-
/** Accepts an issued token, or
|
|
219
|
+
/** Accepts an issued token, or the static one so a client that can send a header still works. */
|
|
200
220
|
async verifyAccessToken(token) {
|
|
201
|
-
if (constantTimeEquals(token, this.
|
|
221
|
+
if (this.staticToken && constantTimeEquals(token, this.staticToken)) {
|
|
202
222
|
// requireBearerAuth refuses a token with no expiry, and this one never expires.
|
|
203
223
|
return { token, clientId: 'static', scopes: [], expiresAt: Math.floor(Date.now() / 1000) + TOKEN_TTL };
|
|
204
224
|
}
|
|
@@ -211,13 +231,27 @@ export class SingleUserOAuthProvider {
|
|
|
211
231
|
await this.store.remove(`token:${token}`);
|
|
212
232
|
throw new InvalidTokenError('Access token has expired');
|
|
213
233
|
}
|
|
214
|
-
|
|
234
|
+
// `extra.address` is where the tools read the caller's identity from; a token that names
|
|
235
|
+
// nobody leaves it unset, and everything falls back to the shared identity.
|
|
236
|
+
return {
|
|
237
|
+
token,
|
|
238
|
+
clientId: stored.clientId,
|
|
239
|
+
scopes: stored.scopes,
|
|
240
|
+
expiresAt: stored.expiresAt,
|
|
241
|
+
...(stored.address ? { extra: { address: stored.address } } : {})
|
|
242
|
+
};
|
|
215
243
|
}
|
|
216
244
|
async revokeToken(_client, request) {
|
|
217
245
|
await this.store.remove(`token:${request.token}`);
|
|
218
246
|
await this.store.remove(`refresh:${request.token}`);
|
|
219
247
|
}
|
|
220
248
|
}
|
|
249
|
+
/** One shared credential, which is all a self-hosted server needs. */
|
|
250
|
+
export class SingleUserOAuthProvider extends OAuthProvider {
|
|
251
|
+
constructor(accessToken) {
|
|
252
|
+
super(tokenLogin(accessToken), accessToken);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
221
255
|
/** PKCE helper, used by the tests to drive the flow the way a real client would. */
|
|
222
256
|
export function pkce() {
|
|
223
257
|
const verifier = randomBytes(32).toString('base64url');
|
package/dist/oauth.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oauth.js","sourceRoot":"","sources":["../src/oauth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AACtE,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AAChE,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAEhC,OAAO,EAAE,iBAAiB,EAAE,MAAM,iDAAiD,CAAA;AAKnF,OAAO,EAAE,kBAAkB,EAAwB,MAAM,iBAAiB,CAAA;AAE1E;;;;;;;;GAQG;AAEH,MAAM,QAAQ,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAA;AAC/B,MAAM,SAAS,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAA;
|
|
1
|
+
{"version":3,"file":"oauth.js","sourceRoot":"","sources":["../src/oauth.ts"],"names":[],"mappings":"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"}
|
package/dist/preview.d.ts
CHANGED
|
@@ -16,6 +16,8 @@ export interface AssetChange {
|
|
|
16
16
|
to: string;
|
|
17
17
|
amount: string;
|
|
18
18
|
humanAmount?: string;
|
|
19
|
+
/** Set for an ERC-721 transfer, which moves this one token rather than an amount. */
|
|
20
|
+
tokenId?: string;
|
|
19
21
|
}
|
|
20
22
|
export interface TxPreview {
|
|
21
23
|
chain: string;
|
|
@@ -49,6 +51,11 @@ export interface RawTx {
|
|
|
49
51
|
data?: string;
|
|
50
52
|
value?: string;
|
|
51
53
|
}
|
|
54
|
+
export declare function enrichTransfers(chain: ChainName, logs: readonly {
|
|
55
|
+
address: string;
|
|
56
|
+
topics: readonly string[];
|
|
57
|
+
data: string;
|
|
58
|
+
}[]): Promise<AssetChange[]>;
|
|
52
59
|
/**
|
|
53
60
|
* Build the human-readable preview shown in the wallet before signing: decoded calldata
|
|
54
61
|
* plus a simulation of the outcome. Never throws — a preview that cannot be built is
|
package/dist/preview.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"preview.d.ts","sourceRoot":"","sources":["../src/preview.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAE3C,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,yEAAyE;IACzE,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,IAAI,EAAE,MAAM,CAAA;IACZ,EAAE,EAAE,MAAM,CAAA;IACV,MAAM,EAAE,MAAM,CAAA;IACd,WAAW,CAAC,EAAE,MAAM,CAAA;
|
|
1
|
+
{"version":3,"file":"preview.d.ts","sourceRoot":"","sources":["../src/preview.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAE3C,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,yEAAyE;IACzE,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,IAAI,EAAE,MAAM,CAAA;IACZ,EAAE,EAAE,MAAM,CAAA;IACV,MAAM,EAAE,MAAM,CAAA;IACd,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,qFAAqF;IACrF,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAA;IACb,EAAE,EAAE,MAAM,CAAA;IACV,gFAAgF;IAChF,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,iEAAiE;IACjE,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,OAAO,CAAC,EAAE;QACR,YAAY,EAAE,MAAM,CAAA;QACpB,SAAS,EAAE,MAAM,CAAA;QACjB,MAAM,EAAE,YAAY,EAAE,CAAA;QACtB,kFAAkF;QAClF,MAAM,CAAC,EAAE,MAAM,CAAA;QACf,QAAQ,CAAC,EAAE,MAAM,CAAA;QACjB,wFAAwF;QACxF,MAAM,EAAE,UAAU,GAAG,SAAS,CAAA;QAC9B,KAAK,CAAC,EAAE,MAAM,CAAA;KACf,CAAA;IACD,UAAU,CAAC,EAAE;QACX,OAAO,EAAE,OAAO,CAAA;QAChB,WAAW,CAAC,EAAE,MAAM,CAAA;QACpB,KAAK,CAAC,EAAE,MAAM,CAAA;QACd,YAAY,EAAE,WAAW,EAAE,CAAA;KAC5B,CAAA;CACF;AAED,MAAM,WAAW,KAAK;IACpB,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAyGD,wBAAsB,eAAe,CACnC,KAAK,EAAE,SAAS,EAChB,IAAI,EAAE,SAAS;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,EAAE,0BAiC9E;AA8CD;;;;GAIG;AACH,wBAAsB,cAAc,CAAC,KAAK,EAAE,SAAS,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CAgCnG"}
|
package/dist/preview.js
CHANGED
|
@@ -94,11 +94,23 @@ async function decodeCalldata(chain, tx) {
|
|
|
94
94
|
function topicToAddress(topic) {
|
|
95
95
|
return `0x${topic.slice(-40)}`;
|
|
96
96
|
}
|
|
97
|
-
async function enrichTransfers(chain, logs) {
|
|
97
|
+
export async function enrichTransfers(chain, logs) {
|
|
98
98
|
const transfers = logs.filter((log) => log.topics[0]?.toLowerCase() === TRANSFER_TOPIC && log.topics.length >= 3);
|
|
99
99
|
return Promise.all(transfers.map(async (log) => {
|
|
100
|
-
const amount = log.data && log.data !== '0x' ? BigInt(log.data).toString() : '0';
|
|
101
100
|
const meta = await tokenMeta(chain, log.address).catch(() => ({ symbol: undefined, decimals: undefined }));
|
|
101
|
+
// ERC-721 shares ERC-20's Transfer topic but indexes the token id as a fourth topic,
|
|
102
|
+
// leaving the data empty — read as ERC-20, a mint looks like a transfer of nothing.
|
|
103
|
+
if (log.topics.length === 4) {
|
|
104
|
+
return {
|
|
105
|
+
token: log.address,
|
|
106
|
+
symbol: meta.symbol,
|
|
107
|
+
from: topicToAddress(log.topics[1]),
|
|
108
|
+
to: topicToAddress(log.topics[2]),
|
|
109
|
+
amount: '1',
|
|
110
|
+
tokenId: BigInt(log.topics[3]).toString()
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
const amount = log.data && log.data !== '0x' ? BigInt(log.data).toString() : '0';
|
|
102
114
|
return {
|
|
103
115
|
token: log.address,
|
|
104
116
|
symbol: meta.symbol,
|
package/dist/preview.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"preview.js","sourceRoot":"","sources":["../src/preview.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkC,kBAAkB,EAAE,WAAW,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,MAAM,CAAA;AACvH,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAC7C,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,SAAS,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAA;AACvF,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAA;AACvF,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"preview.js","sourceRoot":"","sources":["../src/preview.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A signature that outlives the tool call that asked for it.
|
|
3
|
+
*
|
|
4
|
+
* Approving happens on a human's schedule. A browser signer is told to come — the tab opens
|
|
5
|
+
* and the badge flashes — but a phone wallet is only as loud as the wallet itself, and some
|
|
6
|
+
* send no notification at all. So the wait routinely outlives whatever timeout the MCP
|
|
7
|
+
* client applies, and the agent is left holding a tool call that never returns while the
|
|
8
|
+
* request is still perfectly alive in the wallet.
|
|
9
|
+
*
|
|
10
|
+
* Each request gets an id and outlives its call. Settling quickly still returns inline, so
|
|
11
|
+
* the common case — a browser tab that pops up and is approved in seconds — is unchanged.
|
|
12
|
+
* Past that the call hands back the id and the agent collects the result later.
|
|
13
|
+
*
|
|
14
|
+
* Held in memory on purpose: a request is only meaningful while the socket or WalletConnect
|
|
15
|
+
* session that carries it is alive, and both die with the process anyway.
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* How long to wait on a signer that has been told to come — the browser page, whose tab
|
|
19
|
+
* opens and whose title flashes. Comfortably under any MCP client's tool timeout.
|
|
20
|
+
*
|
|
21
|
+
* A signer that cannot raise the alarm does not use this at all: it calls `waiting()` the
|
|
22
|
+
* moment the request is with the wallet, and the call returns then. Waiting on a phone that
|
|
23
|
+
* never buzzed is dead time either way.
|
|
24
|
+
*/
|
|
25
|
+
export declare const GRACE_MS = 25000;
|
|
26
|
+
export type SigningState = 'pending' | 'done' | 'failed';
|
|
27
|
+
export interface SigningRequest {
|
|
28
|
+
id: string;
|
|
29
|
+
identity: string;
|
|
30
|
+
/** What is being asked for, in a line, so a later check can say what it was. */
|
|
31
|
+
summary: string;
|
|
32
|
+
signer: 'browser' | 'phone';
|
|
33
|
+
/** Waiting on a person, or on the chain. They deserve different things said about them. */
|
|
34
|
+
stage: 'approval' | 'mining';
|
|
35
|
+
/** Known once approved, so a request can be followed on an explorer before it settles. */
|
|
36
|
+
txHash?: string;
|
|
37
|
+
startedAt: number;
|
|
38
|
+
state: SigningState;
|
|
39
|
+
settledAt?: number;
|
|
40
|
+
result?: unknown;
|
|
41
|
+
error?: string;
|
|
42
|
+
}
|
|
43
|
+
/** How a signing job says where it has got to. */
|
|
44
|
+
export interface SigningProgress {
|
|
45
|
+
/**
|
|
46
|
+
* The request is with the wallet and only a human is left. Everything that fails quickly —
|
|
47
|
+
* no session, an unapproved chain, a reverted simulation — has already thrown.
|
|
48
|
+
*/
|
|
49
|
+
waiting: () => void;
|
|
50
|
+
/** Approved and broadcast. Nothing is settled until it is mined. */
|
|
51
|
+
mining: (txHash: string) => void;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Run a signing request, waiting only as long as a tool call reasonably can.
|
|
55
|
+
*
|
|
56
|
+
* The work starts here either way — returning `done: false` means nobody has approved yet,
|
|
57
|
+
* never that nothing was asked.
|
|
58
|
+
*/
|
|
59
|
+
export declare function signingCall<T>(context: {
|
|
60
|
+
identity: string;
|
|
61
|
+
summary: string;
|
|
62
|
+
signer: 'browser' | 'phone';
|
|
63
|
+
graceMs?: number;
|
|
64
|
+
}, run: (progress: SigningProgress) => Promise<T>): Promise<{
|
|
65
|
+
done: true;
|
|
66
|
+
result: T;
|
|
67
|
+
} | {
|
|
68
|
+
done: false;
|
|
69
|
+
request: SigningRequest;
|
|
70
|
+
}>;
|
|
71
|
+
/**
|
|
72
|
+
* Collect a request handed back earlier, waiting out another grace period if it is still
|
|
73
|
+
* pending — so an agent that checks in a loop paces itself rather than spinning.
|
|
74
|
+
*
|
|
75
|
+
* Scoped to the caller: an id is unguessable, but on a server carrying several people that
|
|
76
|
+
* is not the reason one of them cannot read another's signature.
|
|
77
|
+
*/
|
|
78
|
+
export declare function collectSigningRequest(id: string, identity: string, graceMs?: number): Promise<SigningRequest>;
|
|
79
|
+
/** Everything this identity still has in front of a wallet. */
|
|
80
|
+
export declare function pendingSigningRequests(identity: string): SigningRequest[];
|
|
81
|
+
//# sourceMappingURL=signing-requests.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"signing-requests.d.ts","sourceRoot":"","sources":["../src/signing-requests.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;GAeG;AAEH;;;;;;;GAOG;AACH,eAAO,MAAM,QAAQ,QAAS,CAAA;AAK9B,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,MAAM,GAAG,QAAQ,CAAA;AAExD,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAA;IACV,QAAQ,EAAE,MAAM,CAAA;IAChB,gFAAgF;IAChF,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,SAAS,GAAG,OAAO,CAAA;IAC3B,2FAA2F;IAC3F,KAAK,EAAE,UAAU,GAAG,QAAQ,CAAA;IAC5B,0FAA0F;IAC1F,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,SAAS,EAAE,MAAM,CAAA;IACjB,KAAK,EAAE,YAAY,CAAA;IACnB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED,kDAAkD;AAClD,MAAM,WAAW,eAAe;IAC9B;;;OAGG;IACH,OAAO,EAAE,MAAM,IAAI,CAAA;IACnB,oEAAoE;IACpE,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAA;CACjC;AAuCD;;;;;GAKG;AACH,wBAAsB,WAAW,CAAC,CAAC,EACjC,OAAO,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,EAC7F,GAAG,EAAE,CAAC,QAAQ,EAAE,eAAe,KAAK,OAAO,CAAC,CAAC,CAAC,GAC7C,OAAO,CAAC;IAAE,IAAI,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,CAAC,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,OAAO,EAAE,cAAc,CAAA;CAAE,CAAC,CA6D/E;AAED;;;;;;GAMG;AACH,wBAAsB,qBAAqB,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,SAAW,GAAG,OAAO,CAAC,cAAc,CAAC,CAYrH;AAED,+DAA+D;AAC/D,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,GAAG,cAAc,EAAE,CAGzE"}
|