@zkproofport-ai/sdk 0.2.9 → 0.2.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +232 -18
- package/dist/arcWallet.d.ts +50 -0
- package/dist/arcWallet.d.ts.map +1 -0
- package/dist/arcWallet.js +158 -0
- package/dist/arcWallet.js.map +1 -0
- package/dist/attestation.d.ts +5 -1
- package/dist/attestation.d.ts.map +1 -1
- package/dist/attestation.js +21 -2
- package/dist/attestation.js.map +1 -1
- package/dist/cdp.d.ts +162 -0
- package/dist/cdp.d.ts.map +1 -0
- package/dist/cdp.js +78 -0
- package/dist/cdp.js.map +1 -0
- package/dist/circuits.d.ts +121 -0
- package/dist/circuits.d.ts.map +1 -0
- package/dist/circuits.js +129 -0
- package/dist/circuits.js.map +1 -0
- package/dist/constants.d.ts +8 -2
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +19 -4
- package/dist/constants.js.map +1 -1
- package/dist/delegation.d.ts +102 -0
- package/dist/delegation.d.ts.map +1 -0
- package/dist/delegation.js +121 -0
- package/dist/delegation.js.map +1 -0
- package/dist/extract.d.ts +46 -12
- package/dist/extract.d.ts.map +1 -1
- package/dist/extract.js +92 -30
- package/dist/extract.js.map +1 -1
- package/dist/flow.d.ts +13 -0
- package/dist/flow.d.ts.map +1 -1
- package/dist/flow.js +90 -3
- package/dist/flow.js.map +1 -1
- package/dist/index.d.ts +12 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +21 -0
- package/dist/index.js.map +1 -1
- package/dist/inputs.d.ts +12 -0
- package/dist/inputs.d.ts.map +1 -1
- package/dist/inputs.js +13 -2
- package/dist/inputs.js.map +1 -1
- package/dist/nanopayment.d.ts +71 -0
- package/dist/nanopayment.d.ts.map +1 -0
- package/dist/nanopayment.js +77 -0
- package/dist/nanopayment.js.map +1 -0
- package/dist/payment.d.ts +73 -0
- package/dist/payment.d.ts.map +1 -0
- package/dist/payment.js +167 -0
- package/dist/payment.js.map +1 -0
- package/dist/prove.d.ts +7 -0
- package/dist/prove.d.ts.map +1 -1
- package/dist/prove.js +2 -0
- package/dist/prove.js.map +1 -1
- package/dist/typedAction.d.ts +3 -0
- package/dist/typedAction.d.ts.map +1 -0
- package/dist/typedAction.js +50 -0
- package/dist/typedAction.js.map +1 -0
- package/dist/types.d.ts +150 -3
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +9 -6
- package/dist/types.js.map +1 -1
- package/dist/usdc.d.ts +63 -0
- package/dist/usdc.d.ts.map +1 -0
- package/dist/usdc.js +78 -0
- package/dist/usdc.js.map +1 -0
- package/dist/wallets.d.ts +96 -0
- package/dist/wallets.d.ts.map +1 -0
- package/dist/wallets.js +214 -0
- package/dist/wallets.js.map +1 -0
- package/package.json +40 -3
package/README.md
CHANGED
|
@@ -1,46 +1,102 @@
|
|
|
1
1
|
# @zkproofport-ai/sdk
|
|
2
2
|
|
|
3
|
-
Client SDK for ZKProofport zero-knowledge
|
|
3
|
+
Client SDK for ZKProofport zero-knowledge proofs, including experimental exact-action authorization on Arc Testnet.
|
|
4
4
|
|
|
5
5
|
## Overview
|
|
6
6
|
|
|
7
7
|
@zkproofport-ai/sdk is a TypeScript SDK for generating privacy-preserving zero-knowledge proofs using Coinbase KYC attestations and OIDC JWT tokens. Generate a proof with a single function call, or fine-tune each step for custom workflows.
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
ZKProofport has a TEE-based proving architecture. Enclave encryption and hardware attestation depend on the selected endpoint and its returned evidence; see the security requirements below.
|
|
10
10
|
|
|
11
|
-
##
|
|
11
|
+
## Paying for a proof
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
A service tells you what it charges. Ask for a proof and the answer is either
|
|
14
|
+
the proof or a `402` listing the chains it takes USDC on — you pick one.
|
|
14
15
|
|
|
15
|
-
|
|
16
|
+
For supported x402 offers, the payer signs an authorization and the payment rail settles it. Arc Gateway nanopayments spend an already funded Gateway balance; its initial deposit is an on-chain transaction requiring gas. A USDC wallet balance alone is insufficient for nanopayments. Wallet, chain and signing-domain compatibility must match the actual offer.
|
|
16
17
|
|
|
17
|
-
|
|
18
|
-
2. The response includes `teePublicKey` — the TEE's attested X25519 public key (cryptographically bound to the Nitro Enclave via COSE Sign1 attestation)
|
|
19
|
-
3. The SDK generates an ephemeral X25519 keypair, performs ECDH key agreement, and encrypts all circuit inputs with AES-256-GCM
|
|
20
|
-
4. The encrypted payload is sent to the server, which relays it blindly to the TEE
|
|
21
|
-
5. The TEE decrypts, generates the ZK proof, and returns it
|
|
18
|
+
Supported payment-wallet adapters:
|
|
22
19
|
|
|
23
|
-
|
|
20
|
+
```ts
|
|
21
|
+
import {
|
|
22
|
+
generateProof,
|
|
23
|
+
walletFromPrivateKey, // a raw key
|
|
24
|
+
walletFromCdp, // a Coinbase CDP server wallet
|
|
25
|
+
walletFromCircle, // a Circle developer-controlled wallet
|
|
26
|
+
walletFromArcAgent, // an existing Circle Agent Wallet through Circle CLI
|
|
27
|
+
walletFor, // walletFor('arc') selects the same adapter from environment
|
|
28
|
+
} from '@zkproofport-ai/sdk';
|
|
29
|
+
|
|
30
|
+
const proof = await generateProof(
|
|
31
|
+
config,
|
|
32
|
+
{
|
|
33
|
+
attestation: signer, // proves who you are
|
|
34
|
+
payment: await walletFromPrivateKey(process.env.PAYMENT_KEY!), // pays
|
|
35
|
+
},
|
|
36
|
+
{ circuit: 'coinbase_kyc' },
|
|
37
|
+
);
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
The two wallets are separate on purpose. The attestation wallet is fixed — it
|
|
41
|
+
is the one your KYC attestation is bound to. The paying wallet is whichever one
|
|
42
|
+
holds USDC.
|
|
43
|
+
|
|
44
|
+
To choose a chain rather than take the first offered, pass `payOn` with a name
|
|
45
|
+
from the service's own list:
|
|
46
|
+
|
|
47
|
+
```ts
|
|
48
|
+
const offers = paymentOffers(await requestChallenge(config, 'coinbase_kyc'));
|
|
49
|
+
// offers: [{ networkName, amount, asset, payTo }, ...]
|
|
50
|
+
|
|
51
|
+
await generateProof(config, { attestation: signer, payment }, {
|
|
52
|
+
circuit: 'coinbase_kyc',
|
|
53
|
+
payOn: offers[0].networkName,
|
|
54
|
+
});
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Naming a chain the service does not offer is an error listing what it does. It
|
|
58
|
+
never quietly pays on a different one.
|
|
59
|
+
|
|
60
|
+
From the command line:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
zkproofport-prove coinbase_kyc --pay-with circle --pay-on <chain>
|
|
64
|
+
zkproofport-prove coinbase_kyc --pay-with cdp
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
`--pay-with cdp` needs `CDP_API_KEY_ID`, `CDP_API_KEY_SECRET` and
|
|
68
|
+
`CDP_WALLET_SECRET`; `--pay-with circle` needs `CIRCLE_API_KEY`,
|
|
69
|
+
`CIRCLE_ENTITY_SECRET` and `CIRCLE_WALLET_ID`; `--pay-with key` needs
|
|
70
|
+
`PAYMENT_PRIVATE_KEY`. For the existing Circle Agent Wallet, explicitly select `--pay-with arc`; Circle CLI owns the login, and `ARC_AGENT_WALLET` selects its wallet. With exactly one key/CDP/developer-controlled wallet configured you can omit
|
|
71
|
+
the flag. With more than one, naming it is required — a wallet is money, and
|
|
72
|
+
guessing which account it leaves is not a default worth having.
|
|
73
|
+
|
|
74
|
+
## Encryption and attestation
|
|
24
75
|
|
|
25
|
-
|
|
26
|
-
|
|
76
|
+
When the selected endpoint supplies a supported attested `teePublicKey`, the SDK encrypts inputs with X25519 ECDH + AES-256-GCM. The host relays ciphertext to the enclave; Nitro mode rejects plaintext inputs. Validate the returned attestation against the required trust policy.
|
|
77
|
+
|
|
78
|
+
An endpoint without that key receives readable circuit inputs over HTTPS and provides no hardware-attestation guarantee. The current Arc staging demo uses that mode. HTTPS transport encryption does not make the prover a blind relay. A valid public proof can hide the credential-holder address from the relying dApp without establishing enclave execution. Only claim hardware-attested proving when the actual attestation supports it.
|
|
27
79
|
|
|
28
80
|
## Installation
|
|
29
81
|
|
|
30
82
|
```bash
|
|
31
|
-
npm install @zkproofport-ai/sdk ethers
|
|
83
|
+
npm install @zkproofport-ai/sdk@latest ethers
|
|
32
84
|
```
|
|
33
85
|
|
|
86
|
+
Arc support described here requires SDK/MCP **0.2.11 or later**. Install from npm and check the resolved version. Release Please manages package versions and the release workflow publishes them; repository source changes alone do not update `@latest`.
|
|
87
|
+
|
|
34
88
|
## Prerequisites
|
|
35
89
|
|
|
36
90
|
**For Coinbase circuits** (`coinbase_kyc`, `coinbase_country`):
|
|
37
91
|
|
|
38
92
|
1. **Coinbase account with KYC verification** — Complete identity verification on [Coinbase](https://www.coinbase.com/)
|
|
39
93
|
2. **Coinbase KYC EAS attestation on Base** — Obtain an attestation via [Coinbase Verifications](https://www.coinbase.com/onchain-verify). This creates an on-chain EAS attestation on Base linked to your wallet address.
|
|
40
|
-
3. **
|
|
94
|
+
3. **Credential signer** (required) — A local signer for the wallet holding the EAS attestation. The CLI uses `ATTESTATION_KEY`; programmatic callers can supply a compatible `ProofportSigner`. Keep key material outside model context.
|
|
41
95
|
|
|
42
96
|
**For OIDC circuits** (`oidc_domain`): No wallet or attestation needed — just a JWT `id_token` from your OIDC provider.
|
|
43
97
|
|
|
98
|
+
**For the action-bound circuit** (`arc_eligibility`): the same Coinbase KYC attestation as above. What differs is what the wallet signs — see below.
|
|
99
|
+
|
|
44
100
|
## Quick Start
|
|
45
101
|
|
|
46
102
|
```typescript
|
|
@@ -59,6 +115,160 @@ const verification = await verifyProof(result);
|
|
|
59
115
|
console.log('Valid:', verification.valid);
|
|
60
116
|
```
|
|
61
117
|
|
|
118
|
+
|
|
119
|
+
## Binding a proof to one action (experimental, testnet only)
|
|
120
|
+
|
|
121
|
+
> **Experimental. Testnet only.**
|
|
122
|
+
>
|
|
123
|
+
> `arc_eligibility` is deployed experimentally on **Arc Testnet, chain 5042002**, not mainnet. The verifier is `0xCbC8E63fF92659E8B44cFF117D33005Bb669a018`; the Ledger House EligibilityGate is `0xD0F3eE648386B59B484157332E736388Fcc41F47`. Its public-input layout and deployment may change. Do not put it in front of real funds. The circuits that are generally available are
|
|
124
|
+
> `coinbase_kyc`, `coinbase_country` and `oidc_domain`.
|
|
125
|
+
|
|
126
|
+
### The problem it solves
|
|
127
|
+
|
|
128
|
+
Every other circuit here has the wallet sign `signal_hash`, which is
|
|
129
|
+
`keccak256(address, scope, circuitId)`. That value is the same for a given
|
|
130
|
+
wallet and scope no matter what the proof is later used for, so:
|
|
131
|
+
|
|
132
|
+
- **It commits to no action.** A proof produced to deposit into one vault
|
|
133
|
+
verifies just as well at a different vault, for a different amount, from a
|
|
134
|
+
different caller, with no deadline. A verifier that checks
|
|
135
|
+
`msg.sender == expectedCaller` gains nothing if the proof never committed to
|
|
136
|
+
that caller.
|
|
137
|
+
- **The person signing cannot read what they approve.** `personal_sign` over 32
|
|
138
|
+
opaque bytes shows a hex string. That is tolerable while a proof only asserts
|
|
139
|
+
"this wallet is KYC'd"; it is not once an agent moves money with it.
|
|
140
|
+
|
|
141
|
+
### What changes
|
|
142
|
+
|
|
143
|
+
Pass an `action` and the wallet signs an [EIP-712](https://eips.ethereum.org/EIPS/eip-712)
|
|
144
|
+
typed structure instead. You define the structure — this SDK keeps no registry
|
|
145
|
+
of action shapes and never invents one.
|
|
146
|
+
|
|
147
|
+
```typescript
|
|
148
|
+
const result = await generateProof(
|
|
149
|
+
config,
|
|
150
|
+
{ attestation: attestationSigner },
|
|
151
|
+
{
|
|
152
|
+
circuit: 'arc_eligibility',
|
|
153
|
+
scope: 'my-app',
|
|
154
|
+
action: {
|
|
155
|
+
domain: {
|
|
156
|
+
name: 'MyVault',
|
|
157
|
+
version: '1',
|
|
158
|
+
chainId: 5042002,
|
|
159
|
+
verifyingContract: vaultAddress, // binds the signature to ONE contract
|
|
160
|
+
},
|
|
161
|
+
types: {
|
|
162
|
+
Deposit: [
|
|
163
|
+
{ name: 'amount', type: 'uint256' },
|
|
164
|
+
{ name: 'nonce', type: 'uint256' },
|
|
165
|
+
{ name: 'expiry', type: 'uint64' },
|
|
166
|
+
],
|
|
167
|
+
},
|
|
168
|
+
primaryType: 'Deposit',
|
|
169
|
+
message: { amount: 100_000n, nonce: 1n, expiry: deadline },
|
|
170
|
+
},
|
|
171
|
+
},
|
|
172
|
+
);
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
The wallet renders `amount`, `nonce` and `expiry` by name for the person to
|
|
176
|
+
read. Two 32-byte hashes reach the circuit — the EIP-712 domain separator and
|
|
177
|
+
the hash of the action — and the circuit proves the KYC'd key signed them. It
|
|
178
|
+
never learns what the action was, so nothing about vaults or USDC is baked into
|
|
179
|
+
it: a grant of authority or an agreement in prose works the same way.
|
|
180
|
+
|
|
181
|
+
```typescript
|
|
182
|
+
// Free-form text is a valid shape.
|
|
183
|
+
types: { Agreement: [{ name: 'terms', type: 'string' }] },
|
|
184
|
+
primaryType: 'Agreement',
|
|
185
|
+
message: { terms: 'Deposit 0.1 USDC into the KYC-gated vault' },
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
A contract cannot enforce prose, though. To check an amount on-chain, the
|
|
189
|
+
amount has to be its own field.
|
|
190
|
+
|
|
191
|
+
### What your verifier does
|
|
192
|
+
|
|
193
|
+
It recomputes both hashes from the call it is about to run and refuses a
|
|
194
|
+
mismatch:
|
|
195
|
+
|
|
196
|
+
```solidity
|
|
197
|
+
bytes32 domainSeparator = _domainSeparatorV4(); // this contract, this chain
|
|
198
|
+
bytes32 actionHash = keccak256(abi.encode(
|
|
199
|
+
DEPOSIT_TYPEHASH, amount, nonce, uint64(expiry)
|
|
200
|
+
));
|
|
201
|
+
require(publicInputs.domainSeparator == domainSeparator, "wrong contract");
|
|
202
|
+
require(publicInputs.actionHash == actionHash, "wrong action");
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
Public inputs arrive in this order — read off the compiled ABI, 192 fields of
|
|
206
|
+
one byte each:
|
|
207
|
+
|
|
208
|
+
| Field | Byte range |
|
|
209
|
+
|---|---|
|
|
210
|
+
| `signal_hash` | 0–31 |
|
|
211
|
+
| `domain_separator` | 32–63 |
|
|
212
|
+
| `action_hash` | 64–95 |
|
|
213
|
+
| `signer_list_merkle_root` | 96–127 |
|
|
214
|
+
| `scope` | 128–159 |
|
|
215
|
+
| `nullifier` | 160–191 |
|
|
216
|
+
|
|
217
|
+
`signal_hash` is still present, and nobody signs it: the nullifier derives from
|
|
218
|
+
it, exactly as on the other Coinbase circuits. Deriving the nullifier from the
|
|
219
|
+
signed action instead would give a different nullifier per action and destroy
|
|
220
|
+
the one-per-person property it exists for.
|
|
221
|
+
|
|
222
|
+
### Omitting `action`
|
|
223
|
+
|
|
224
|
+
`arc_eligibility` requires `action`; omitting it is rejected. Other circuits reject `action` and retain their existing `personal_sign` flow. The application must verify the exact target, operational wallet, amount, nonce and deadline as well as the proof.
|
|
225
|
+
|
|
226
|
+
## Arc Circle Agent Wallet path — EXPERIMENTAL
|
|
227
|
+
|
|
228
|
+
Use the existing Circle CLI login and selected Arc Agent Wallet; do not create or switch wallets as part of proof generation. Install the CLI if needed, then let the user complete any missing login locally. Keep `ATTESTATION_KEY` and login secrets outside prompts, model context, logs and committed configuration.
|
|
229
|
+
|
|
230
|
+
```bash
|
|
231
|
+
npm install -g @circle-fin/cli
|
|
232
|
+
circle wallet list --chain ARC-TESTNET --type agent
|
|
233
|
+
# Set ARC_AGENT_WALLET to the user's existing, approved wallet B address.
|
|
234
|
+
circle gateway balance --address "$ARC_AGENT_WALLET" --chain ARC-TESTNET --output json
|
|
235
|
+
# Only when the user has approved this funding amount:
|
|
236
|
+
circle gateway deposit --amount 0.1 --address "$ARC_AGENT_WALLET" --chain ARC-TESTNET --method direct
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
The payment adapter resolves Circle's backing EOA for Gateway authorization. The operational smart-wallet address remains Wallet B for the action and stake; do not substitute the backing EOA into the action's `delegate` field. `walletFromArcAgent({address: process.env.ARC_AGENT_WALLET, chain: 'ARC-TESTNET'})` and `walletFor('arc')` provide the same payment path.
|
|
240
|
+
|
|
241
|
+
After the user reviews the action and the live x402 offer, save those exact approved objects locally as `approved-action.json` and `approved-payment.json`:
|
|
242
|
+
|
|
243
|
+
```typescript
|
|
244
|
+
import { readFile } from 'node:fs/promises';
|
|
245
|
+
import {
|
|
246
|
+
createConfig, fromPrivateKey, generateProof, verifyProof, walletFor,
|
|
247
|
+
type ProofParams, type ApprovedPayment,
|
|
248
|
+
} from '@zkproofport-ai/sdk';
|
|
249
|
+
|
|
250
|
+
const config = createConfig({baseUrl: 'https://stg-ai.zkproofport.app'});
|
|
251
|
+
const action: NonNullable<ProofParams['action']> = JSON.parse(await readFile('approved-action.json', 'utf8'));
|
|
252
|
+
const approvedPayment: ApprovedPayment = JSON.parse(await readFile('approved-payment.json', 'utf8'));
|
|
253
|
+
const result = await generateProof(config, {
|
|
254
|
+
attestation: fromPrivateKey(process.env.ATTESTATION_KEY!), // local credential holder A
|
|
255
|
+
payment: await walletFor('arc'), // existing Circle wallet B
|
|
256
|
+
}, {
|
|
257
|
+
circuit: 'arc_eligibility', scope: 'ledger-house', action,
|
|
258
|
+
payOn: 'arc-testnet-nano', maxPayment: '0.001', approvedPayment,
|
|
259
|
+
});
|
|
260
|
+
const verification = await verifyProof(result);
|
|
261
|
+
if (!verification.valid) throw new Error('Arc verifier rejected the proof');
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
`approvedPayment` must pin the live offer's `network`, `scheme`, `amount`, `asset`, `payTo`, and `extra: {name, version, verifyingContract}`. `amount` is an integer string in USDC base units (`"1000"` is 0.001 USDC); `maxPayment` is a decimal USDC string (`"0.001"`). A changed fee, recipient, asset, network or Gateway signing domain is rejected before payment signing. Approve the actual offer; do not manufacture its recipient or domain from a documentation example.
|
|
265
|
+
|
|
266
|
+
For the deployed Ledger House gate, use the dApp's exact EIP-712 shape: domain `Ledger House Staking`, version `1`, chain `5042002`, and the gate address above. Its `CredentialDelegation` type contains `delegate: address`, `action: string`, `amount: uint256`, `expiresAt: uint256`, `nonce: string`; the message uses Wallet B, `"stake"`, `"100000"` for 0.1 USDC, and the approved deadline and fresh nonce. **Exact-action authorization** is the user-facing term; existing wire keys and `CredentialDelegation` are unchanged.
|
|
267
|
+
|
|
268
|
+
Generating and verifying a proof does not submit a stake. After a separate stake approval, the operational wallet calls the dApp gate, which verifies the proof and enforces its policy, exact action, unused nonce and deadline atomically. Check the receipt before reporting a position change.
|
|
269
|
+
|
|
270
|
+
The MCP `gateway_balance` and `deposit_to_gateway` helpers currently require `PAYMENT_PRIVATE_KEY`; they do not operate the Circle Agent Wallet. Use the Circle CLI commands above for that wallet. SDK `gatewayBalance` / `ensureGatewayBalance` likewise accept the private-key `NanopaymentWallet` shape. This path documents the supported Arc Testnet offer, not a guarantee for every wallet on every chain.
|
|
271
|
+
|
|
62
272
|
## Configuration
|
|
63
273
|
|
|
64
274
|
```typescript
|
|
@@ -125,7 +335,7 @@ if (result.attestation) {
|
|
|
125
335
|
2. Fetch Coinbase KYC attestation from EAS
|
|
126
336
|
3. Build circuit inputs (Merkle tree, hashes)
|
|
127
337
|
4. **Auto-detect E2E encryption** — if `teePublicKey` is present in server response, encrypt inputs with X25519 ECDH + AES-256-GCM
|
|
128
|
-
5. Generate proof
|
|
338
|
+
5. Generate the proof on the configured prover (enclave-encrypted only for the supported Nitro deployment)
|
|
129
339
|
|
|
130
340
|
**Result fields:**
|
|
131
341
|
|
|
@@ -317,8 +527,8 @@ The proof contains 148 public input fields (32 bytes each):
|
|
|
317
527
|
**Circuit Types:**
|
|
318
528
|
|
|
319
529
|
```typescript
|
|
320
|
-
type CircuitName = 'coinbase_kyc' | 'coinbase_country' | 'oidc_domain';
|
|
321
|
-
type CircuitId = 'coinbase_attestation' | 'coinbase_country_attestation' | 'oidc_domain_attestation';
|
|
530
|
+
type CircuitName = 'coinbase_kyc' | 'coinbase_country' | 'oidc_domain' | 'arc_eligibility';
|
|
531
|
+
type CircuitId = 'coinbase_attestation' | 'coinbase_country_attestation' | 'oidc_domain_attestation' | 'arc_eligibility';
|
|
322
532
|
```
|
|
323
533
|
|
|
324
534
|
**Configuration:**
|
|
@@ -351,6 +561,10 @@ function fromSigner(signer: ethers.Signer): ProofportSigner;
|
|
|
351
561
|
```typescript
|
|
352
562
|
interface ProofParams {
|
|
353
563
|
circuit: CircuitName;
|
|
564
|
+
action?: { domain: { name: string; version: string; chainId: number; verifyingContract: string }; types: Record<string, Array<{name: string; type: string}>>; primaryType: string; message: Record<string, unknown> }; // required only for arc_eligibility
|
|
565
|
+
payOn?: string;
|
|
566
|
+
maxPayment?: string; // decimal USDC
|
|
567
|
+
approvedPayment?: ApprovedPayment;
|
|
354
568
|
scope?: string; // defaults to 'proofport'
|
|
355
569
|
countryList?: string[]; // for coinbase_country only
|
|
356
570
|
isIncluded?: boolean; // for coinbase_country only
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Paying from an Arc agent wallet, through Circle's CLI.
|
|
3
|
+
*
|
|
4
|
+
* ## Why the CLI and not an API
|
|
5
|
+
*
|
|
6
|
+
* An Arc agent wallet is not a key this process can hold. Circle keeps it, and
|
|
7
|
+
* everything that touches it — creating it, reading its balance, signing with
|
|
8
|
+
* it — goes through `@circle-fin/cli`, which authenticates with a login that a
|
|
9
|
+
* person does once. So the integration is a wrapper around that command, and
|
|
10
|
+
* the alternative would be reimplementing Circle's auth, which is both work and
|
|
11
|
+
* a second thing to get wrong.
|
|
12
|
+
*
|
|
13
|
+
* ## What this buys over a private key
|
|
14
|
+
*
|
|
15
|
+
* The wallet carries policies Circle enforces: spending limits per period,
|
|
16
|
+
* recipient allowlists, contract blocklists. A raw key has none of that — it
|
|
17
|
+
* signs whatever it is handed. That is the whole point of an agent holding
|
|
18
|
+
* money: the agent acts on its own, and the limits are not the agent's to
|
|
19
|
+
* ignore.
|
|
20
|
+
*
|
|
21
|
+
* ## What it costs
|
|
22
|
+
*
|
|
23
|
+
* A subprocess per signature, and the CLI must be installed and logged in. Both
|
|
24
|
+
* are checked before signing rather than discovered as a cryptic failure, and
|
|
25
|
+
* the errors here say which of the two is missing and what command fixes it.
|
|
26
|
+
*/
|
|
27
|
+
import type { PaymentWallet } from './types.js';
|
|
28
|
+
/** How Circle names Arc's chains. Not ours to choose. */
|
|
29
|
+
export declare const ARC_CLI_CHAINS: {
|
|
30
|
+
readonly testnet: "ARC-TESTNET";
|
|
31
|
+
readonly mainnet: "ARC";
|
|
32
|
+
};
|
|
33
|
+
export type ArcCliChain = (typeof ARC_CLI_CHAINS)[keyof typeof ARC_CLI_CHAINS];
|
|
34
|
+
/** The agent wallets Circle holds for this login on one chain. */
|
|
35
|
+
export declare function listArcAgentWallets(chain?: ArcCliChain): Promise<string[]>;
|
|
36
|
+
/** Create one. Circle caps an account at five. */
|
|
37
|
+
export declare function createArcAgentWallet(): Promise<string>;
|
|
38
|
+
/**
|
|
39
|
+
* A payment wallet backed by an Arc agent wallet.
|
|
40
|
+
*
|
|
41
|
+
* `address` may be omitted, in which case the single agent wallet on that chain
|
|
42
|
+
* is used — and having none, or several, is an error rather than a guess:
|
|
43
|
+
* paying from a wallet the caller did not name spends somebody's money
|
|
44
|
+
* somewhere they did not choose.
|
|
45
|
+
*/
|
|
46
|
+
export declare function walletFromArcAgent(opts?: {
|
|
47
|
+
address?: string;
|
|
48
|
+
chain?: ArcCliChain;
|
|
49
|
+
}): Promise<PaymentWallet>;
|
|
50
|
+
//# sourceMappingURL=arcWallet.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"arcWallet.d.ts","sourceRoot":"","sources":["../src/arcWallet.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAIH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAIhD,yDAAyD;AACzD,eAAO,MAAM,cAAc;;;CAAsD,CAAC;AAClF,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,OAAO,cAAc,CAAC,CAAC;AAuC/E,kEAAkE;AAClE,wBAAsB,mBAAmB,CAAC,KAAK,GAAE,WAAoC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAKxG;AAED,kDAAkD;AAClD,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,MAAM,CAAC,CAK5D;AAiBD;;;;;;;GAOG;AACH,wBAAsB,kBAAkB,CAAC,IAAI,GAAE;IAC7C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,WAAW,CAAC;CAChB,GAAG,OAAO,CAAC,aAAa,CAAC,CAqE9B"}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Paying from an Arc agent wallet, through Circle's CLI.
|
|
3
|
+
*
|
|
4
|
+
* ## Why the CLI and not an API
|
|
5
|
+
*
|
|
6
|
+
* An Arc agent wallet is not a key this process can hold. Circle keeps it, and
|
|
7
|
+
* everything that touches it — creating it, reading its balance, signing with
|
|
8
|
+
* it — goes through `@circle-fin/cli`, which authenticates with a login that a
|
|
9
|
+
* person does once. So the integration is a wrapper around that command, and
|
|
10
|
+
* the alternative would be reimplementing Circle's auth, which is both work and
|
|
11
|
+
* a second thing to get wrong.
|
|
12
|
+
*
|
|
13
|
+
* ## What this buys over a private key
|
|
14
|
+
*
|
|
15
|
+
* The wallet carries policies Circle enforces: spending limits per period,
|
|
16
|
+
* recipient allowlists, contract blocklists. A raw key has none of that — it
|
|
17
|
+
* signs whatever it is handed. That is the whole point of an agent holding
|
|
18
|
+
* money: the agent acts on its own, and the limits are not the agent's to
|
|
19
|
+
* ignore.
|
|
20
|
+
*
|
|
21
|
+
* ## What it costs
|
|
22
|
+
*
|
|
23
|
+
* A subprocess per signature, and the CLI must be installed and logged in. Both
|
|
24
|
+
* are checked before signing rather than discovered as a cryptic failure, and
|
|
25
|
+
* the errors here say which of the two is missing and what command fixes it.
|
|
26
|
+
*/
|
|
27
|
+
import { execFile } from 'node:child_process';
|
|
28
|
+
import { promisify } from 'node:util';
|
|
29
|
+
const run = promisify(execFile);
|
|
30
|
+
/** How Circle names Arc's chains. Not ours to choose. */
|
|
31
|
+
export const ARC_CLI_CHAINS = { testnet: 'ARC-TESTNET', mainnet: 'ARC' };
|
|
32
|
+
async function circle(args) {
|
|
33
|
+
try {
|
|
34
|
+
const { stdout } = await run('circle', [...args, '--output', 'json'], {
|
|
35
|
+
// Non-interactive: a script has no way to answer the terms prompt, and
|
|
36
|
+
// Circle documents this variable for exactly that.
|
|
37
|
+
env: { ...process.env, CIRCLE_ACCEPT_TERMS: '1' },
|
|
38
|
+
maxBuffer: 8 * 1024 * 1024,
|
|
39
|
+
});
|
|
40
|
+
return JSON.parse(stdout);
|
|
41
|
+
}
|
|
42
|
+
catch (error) {
|
|
43
|
+
const err = error;
|
|
44
|
+
if (err.code === 'ENOENT') {
|
|
45
|
+
throw new Error('Circle CLI is not installed, so an Arc agent wallet cannot sign. Install it with ' +
|
|
46
|
+
'`npm install -g @circle-fin/cli`, then `circle wallet login <email> --testnet`.');
|
|
47
|
+
}
|
|
48
|
+
// The CLI prints a JSON error on stdout even when it exits non-zero.
|
|
49
|
+
let reason = err.stderr?.trim() || err.message || 'unknown error';
|
|
50
|
+
try {
|
|
51
|
+
const parsed = JSON.parse(err.stdout ?? '');
|
|
52
|
+
if (parsed.error?.message) {
|
|
53
|
+
reason = parsed.error.hint ? `${parsed.error.message} (${parsed.error.hint})` : parsed.error.message;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
// stdout was not JSON; the stderr text above is the best there is.
|
|
58
|
+
}
|
|
59
|
+
if (/AUTH_REQUIRED|Not logged in/i.test(reason)) {
|
|
60
|
+
throw new Error(`Circle CLI is not logged in for this environment: ${reason}. ` +
|
|
61
|
+
'Testnet and mainnet are separate logins — `circle wallet login <email> --testnet` for Arc Testnet.');
|
|
62
|
+
}
|
|
63
|
+
throw new Error(`Circle CLI failed: ${reason}`);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
/** The agent wallets Circle holds for this login on one chain. */
|
|
67
|
+
export async function listArcAgentWallets(chain = ARC_CLI_CHAINS.testnet) {
|
|
68
|
+
const answer = (await circle(['wallet', 'list', '--chain', chain, '--type', 'agent']));
|
|
69
|
+
return (answer.data?.wallets ?? []).map((w) => String(w.address)).filter(Boolean);
|
|
70
|
+
}
|
|
71
|
+
/** Create one. Circle caps an account at five. */
|
|
72
|
+
export async function createArcAgentWallet() {
|
|
73
|
+
const answer = (await circle(['wallet', 'create']));
|
|
74
|
+
const address = answer.data?.wallet?.address;
|
|
75
|
+
if (!address)
|
|
76
|
+
throw new Error('Circle CLI created a wallet but reported no address.');
|
|
77
|
+
return address;
|
|
78
|
+
}
|
|
79
|
+
/** The address that actually signs for an agent wallet, per Circle. */
|
|
80
|
+
async function backingEoa(wallet, chain) {
|
|
81
|
+
const answer = (await circle(['gateway', 'balance', '--address', wallet, '--chain', chain]));
|
|
82
|
+
const backer = answer.data?.backingEOA;
|
|
83
|
+
if (!backer) {
|
|
84
|
+
throw new Error(`Circle did not say which address signs for agent wallet ${wallet}. ` +
|
|
85
|
+
'Gateway holds the balance under that address, so paying without it would sign as nobody.');
|
|
86
|
+
}
|
|
87
|
+
return backer;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* A payment wallet backed by an Arc agent wallet.
|
|
91
|
+
*
|
|
92
|
+
* `address` may be omitted, in which case the single agent wallet on that chain
|
|
93
|
+
* is used — and having none, or several, is an error rather than a guess:
|
|
94
|
+
* paying from a wallet the caller did not name spends somebody's money
|
|
95
|
+
* somewhere they did not choose.
|
|
96
|
+
*/
|
|
97
|
+
export async function walletFromArcAgent(opts = {}) {
|
|
98
|
+
const chain = opts.chain ?? ARC_CLI_CHAINS.testnet;
|
|
99
|
+
let address = opts.address;
|
|
100
|
+
if (!address) {
|
|
101
|
+
const wallets = await listArcAgentWallets(chain);
|
|
102
|
+
if (wallets.length === 0) {
|
|
103
|
+
throw new Error(`No Arc agent wallet exists on ${chain}. Create one with \`circle wallet create\`, ` +
|
|
104
|
+
'or pass the address of one that does.');
|
|
105
|
+
}
|
|
106
|
+
if (wallets.length > 1) {
|
|
107
|
+
throw new Error(`${wallets.length} agent wallets exist on ${chain} (${wallets.join(', ')}). ` +
|
|
108
|
+
'Name the one to pay from — picking for you would spend from a wallet nobody chose.');
|
|
109
|
+
}
|
|
110
|
+
address = wallets[0];
|
|
111
|
+
}
|
|
112
|
+
// Which address signs, and therefore which address an authorization must
|
|
113
|
+
// name.
|
|
114
|
+
//
|
|
115
|
+
// An agent wallet is a smart contract; the key that signs for it is a
|
|
116
|
+
// separate address Circle calls the backing EOA, and Gateway holds the
|
|
117
|
+
// deposited balance under THAT one. An authorization whose `from` is the
|
|
118
|
+
// contract address is refused as `invalid_signature`, because the signature
|
|
119
|
+
// recovers to the backer and not to the address the message names.
|
|
120
|
+
const signer = await backingEoa(address, chain);
|
|
121
|
+
return {
|
|
122
|
+
address: signer,
|
|
123
|
+
signTypedData: async (message) => {
|
|
124
|
+
// EIP-712 amounts arrive as BigInt and `JSON.stringify` refuses them
|
|
125
|
+
// outright — "Do not know how to serialize a BigInt". They go over as
|
|
126
|
+
// decimal strings, which is what EIP-712 encoders take for a uint256
|
|
127
|
+
// anyway, so nothing is lost and nothing is rounded.
|
|
128
|
+
// `EIP712Domain` spelled out.
|
|
129
|
+
//
|
|
130
|
+
// viem infers it from the domain's own fields and most libraries follow,
|
|
131
|
+
// but Circle's CLI validates the typed data strictly and refuses a
|
|
132
|
+
// request whose `types` does not declare it: "there is extra data
|
|
133
|
+
// provided in the message (0 < 4)". Declared here to match the domain
|
|
134
|
+
// actually given, field for field.
|
|
135
|
+
const typed = message;
|
|
136
|
+
const domainFields = [
|
|
137
|
+
['name', 'string'],
|
|
138
|
+
['version', 'string'],
|
|
139
|
+
['chainId', 'uint256'],
|
|
140
|
+
['verifyingContract', 'address'],
|
|
141
|
+
].filter(([field]) => typed.domain && typed.domain[field] !== undefined)
|
|
142
|
+
.map(([name, type]) => ({ name, type }));
|
|
143
|
+
const asJson = JSON.stringify({ ...typed, types: { EIP712Domain: domainFields, ...(typed.types ?? {}) } }, (_key, value) => (typeof value === 'bigint' ? value.toString() : value));
|
|
144
|
+
if (process.env.ARC_WALLET_DEBUG)
|
|
145
|
+
console.error('[arc-wallet] 서명 요청 =', asJson);
|
|
146
|
+
const answer = (await circle([
|
|
147
|
+
'wallet', 'sign', 'typed-data', asJson,
|
|
148
|
+
'--address', address, '--chain', chain,
|
|
149
|
+
]));
|
|
150
|
+
const signature = answer.data?.signature;
|
|
151
|
+
if (!signature)
|
|
152
|
+
throw new Error('Circle CLI signed nothing: no signature in its answer.');
|
|
153
|
+
return signature;
|
|
154
|
+
},
|
|
155
|
+
describe: () => `Arc agent wallet ${address} on ${chain}, signing as ${signer}`,
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
//# sourceMappingURL=arcWallet.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"arcWallet.js","sourceRoot":"","sources":["../src/arcWallet.ts"],"names":[],"mappings":"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"}
|
package/dist/attestation.d.ts
CHANGED
|
@@ -5,7 +5,11 @@ import type { CircuitId, EASAttestation, AttestationData, ClientConfig } from '.
|
|
|
5
5
|
export declare function fetchAttestationFromEAS(easGraphqlUrl: string, circuitId: CircuitId, recipientAddress: string): Promise<EASAttestation>;
|
|
6
6
|
/**
|
|
7
7
|
* Fetch raw transaction via eth_getTransactionByHash from an RPC endpoint.
|
|
8
|
-
*
|
|
8
|
+
*
|
|
9
|
+
* Retry policy:
|
|
10
|
+
* - HTTP 429/5xx, ECONNRESET, ETIMEDOUT: MAX_RETRIES (3) attempts, 1s base delay (transient network).
|
|
11
|
+
* - data.result === null (tx not yet indexed): TX_INDEX_MAX_RETRIES (15) attempts, 2s delay.
|
|
12
|
+
* Public RPCs (base.org, base-sepolia) need 5-30s to index a freshly submitted attestation tx.
|
|
9
13
|
*/
|
|
10
14
|
export declare function fetchRawTransaction(rpcUrl: string, txHash: string): Promise<string>;
|
|
11
15
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"attestation.d.ts","sourceRoot":"","sources":["../src/attestation.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,cAAc,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"attestation.d.ts","sourceRoot":"","sources":["../src/attestation.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,cAAc,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAyC3F;;GAEG;AACH,wBAAsB,uBAAuB,CAC3C,aAAa,EAAE,MAAM,EACrB,SAAS,EAAE,SAAS,EACpB,gBAAgB,EAAE,MAAM,GACvB,OAAO,CAAC,cAAc,CAAC,CAkCzB;AAID;;;;;;;GAOG;AACH,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,MAAM,CAAC,CA2DjB;AAID;;;GAGG;AACH,wBAAgB,yBAAyB,CAAC,MAAM,EAAE;IAChD,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,UAAU,CAAC,EAAE,KAAK,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,CAAC;CAChE,GAAG,MAAM,CAuBT;AAID;;;;GAIG;AACH,wBAAgB,qBAAqB,CACnC,cAAc,EAAE,MAAM,EACtB,SAAS,EAAE,SAAS,GACnB;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAsBpC;AAID;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,cAAc,EAAE,MAAM,GAAG,MAAM,CA0BpE;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAEvD;AAID;;;;;;GAMG;AACH,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,YAAY,EACpB,SAAS,EAAE,SAAS,EACpB,gBAAgB,EAAE,MAAM,GACvB,OAAO,CAAC,eAAe,CAAC,CAyB1B"}
|
package/dist/attestation.js
CHANGED
|
@@ -26,6 +26,12 @@ const EAS_ATTESTATIONS_QUERY = `
|
|
|
26
26
|
const MAX_RETRIES = 3;
|
|
27
27
|
const RETRY_DELAY_MS = 1000;
|
|
28
28
|
const RETRYABLE_STATUS = new Set([429, 500, 502, 503, 504]);
|
|
29
|
+
// Public RPCs (e.g. base.org, base-sepolia) can take 5-30s to index a freshly
|
|
30
|
+
// submitted attestation tx. Retry the "result is null" case separately with a
|
|
31
|
+
// larger budget so generateProof doesn't fail immediately after the customer
|
|
32
|
+
// submits their attestation transaction.
|
|
33
|
+
const TX_INDEX_MAX_RETRIES = 15;
|
|
34
|
+
const TX_INDEX_DELAY_MS = 2000;
|
|
29
35
|
// ─── EAS GraphQL fetch ──────────────────────────────────────────────────
|
|
30
36
|
/**
|
|
31
37
|
* Query EAS GraphQL for the latest attestation matching schemaId + recipient.
|
|
@@ -60,10 +66,15 @@ export async function fetchAttestationFromEAS(easGraphqlUrl, circuitId, recipien
|
|
|
60
66
|
// ─── Raw transaction fetch ──────────────────────────────────────────────
|
|
61
67
|
/**
|
|
62
68
|
* Fetch raw transaction via eth_getTransactionByHash from an RPC endpoint.
|
|
63
|
-
*
|
|
69
|
+
*
|
|
70
|
+
* Retry policy:
|
|
71
|
+
* - HTTP 429/5xx, ECONNRESET, ETIMEDOUT: MAX_RETRIES (3) attempts, 1s base delay (transient network).
|
|
72
|
+
* - data.result === null (tx not yet indexed): TX_INDEX_MAX_RETRIES (15) attempts, 2s delay.
|
|
73
|
+
* Public RPCs (base.org, base-sepolia) need 5-30s to index a freshly submitted attestation tx.
|
|
64
74
|
*/
|
|
65
75
|
export async function fetchRawTransaction(rpcUrl, txHash) {
|
|
66
76
|
let lastError;
|
|
77
|
+
let indexAttempts = 0;
|
|
67
78
|
for (let attempt = 0; attempt < MAX_RETRIES; attempt++) {
|
|
68
79
|
try {
|
|
69
80
|
const response = await fetch(rpcUrl, {
|
|
@@ -89,7 +100,15 @@ export async function fetchRawTransaction(rpcUrl, txHash) {
|
|
|
89
100
|
throw new Error(`RPC error: ${data.error.message}`);
|
|
90
101
|
}
|
|
91
102
|
if (!data.result) {
|
|
92
|
-
|
|
103
|
+
// Transaction not yet indexed — retry up to TX_INDEX_MAX_RETRIES times
|
|
104
|
+
// with a longer delay, since public RPCs can lag 5-30s behind the mempool.
|
|
105
|
+
if (indexAttempts < TX_INDEX_MAX_RETRIES) {
|
|
106
|
+
indexAttempts++;
|
|
107
|
+
await new Promise(r => setTimeout(r, TX_INDEX_DELAY_MS));
|
|
108
|
+
attempt--; // do not consume an outer retry slot for indexing waits
|
|
109
|
+
continue;
|
|
110
|
+
}
|
|
111
|
+
throw new Error(`Transaction ${txHash} not found after ${TX_INDEX_MAX_RETRIES} retries (${(TX_INDEX_MAX_RETRIES * TX_INDEX_DELAY_MS) / 1000}s)`);
|
|
93
112
|
}
|
|
94
113
|
return reconstructRawTransaction(data.result);
|
|
95
114
|
}
|
package/dist/attestation.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"attestation.js","sourceRoot":"","sources":["../src/attestation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,EAAE,QAAQ,EAAE,0BAA0B,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAG5G,2EAA2E;AAE3E,MAAM,sBAAsB,GAAG;;;;;;;;;;;;;;;;;;;;CAoB9B,CAAC;AAEF,2EAA2E;AAE3E,MAAM,WAAW,GAAG,CAAC,CAAC;AACtB,MAAM,cAAc,GAAG,IAAI,CAAC;AAC5B,MAAM,gBAAgB,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;AAE5D,2EAA2E;AAE3E;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAC3C,aAAqB,EACrB,SAAoB,EACpB,gBAAwB;IAExB,MAAM,OAAO,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC;IACpC,MAAM,QAAQ,GAAG,OAAO,CAAC,WAAW,CAAC;IAErC,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,aAAa,EAAE;QAC1C,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;QAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;YACnB,KAAK,EAAE,sBAAsB;YAC7B,SAAS,EAAE;gBACT,QAAQ;gBACR,SAAS,EAAE,gBAAgB,CAAC,WAAW,EAAE;aAC1C;SACF,CAAC;KACH,CAAC,CAAC;IAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CAAC,oCAAoC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;IACzE,CAAC;IAED,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;IAEnC,IAAI,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1C,MAAM,IAAI,KAAK,CAAC,sBAAsB,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;IAClE,CAAC;IAED,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,EAAE,YAAY,CAAC;IAC7C,IAAI,CAAC,YAAY,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC/C,MAAM,IAAI,KAAK,CACb,mCAAmC,QAAQ,kBAAkB,gBAAgB,EAAE,CAChF,CAAC;IACJ,CAAC;IAED,OAAO,YAAY,CAAC,CAAC,CAAC,CAAC;AACzB,CAAC;AAED,2EAA2E;AAE3E
|
|
1
|
+
{"version":3,"file":"attestation.js","sourceRoot":"","sources":["../src/attestation.ts"],"names":[],"mappings":"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"}
|