@inco/shield-js 0.0.0-bootstrap.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 +359 -0
- package/dist/binary.d.ts +3 -0
- package/dist/binary.js +16 -0
- package/dist/contracts/abi.d.ts +6800 -0
- package/dist/contracts/abi.js +8836 -0
- package/dist/contracts/index.d.ts +2 -0
- package/dist/contracts/index.js +2 -0
- package/dist/contracts/utils.d.ts +25 -0
- package/dist/contracts/utils.js +28 -0
- package/dist/errors.d.ts +125 -0
- package/dist/errors.js +91 -0
- package/dist/generated/inco/shield/v2/conductor_connect.d.ts +137 -0
- package/dist/generated/inco/shield/v2/conductor_connect.js +141 -0
- package/dist/generated/inco/shield/v2/deposit_pb.d.ts +103 -0
- package/dist/generated/inco/shield/v2/deposit_pb.js +141 -0
- package/dist/generated/inco/shield/v2/drafting_pb.d.ts +279 -0
- package/dist/generated/inco/shield/v2/drafting_pb.js +372 -0
- package/dist/generated/inco/shield/v2/permission_pb.d.ts +443 -0
- package/dist/generated/inco/shield/v2/permission_pb.js +639 -0
- package/dist/generated/inco/shield/v2/query_pb.d.ts +103 -0
- package/dist/generated/inco/shield/v2/query_pb.js +141 -0
- package/dist/generated/inco/shield/v2/types_pb.d.ts +166 -0
- package/dist/generated/inco/shield/v2/types_pb.js +261 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.js +19 -0
- package/dist/shield/client.d.ts +72 -0
- package/dist/shield/client.js +136 -0
- package/dist/shield/convert.d.ts +18 -0
- package/dist/shield/convert.js +152 -0
- package/dist/shield/encryption.d.ts +86 -0
- package/dist/shield/encryption.js +180 -0
- package/dist/shield/envelope.d.ts +14 -0
- package/dist/shield/envelope.js +29 -0
- package/dist/shield/index.d.ts +13 -0
- package/dist/shield/index.js +11 -0
- package/dist/shield/intent.d.ts +977 -0
- package/dist/shield/intent.js +188 -0
- package/dist/shield/rpc.d.ts +72 -0
- package/dist/shield/rpc.js +423 -0
- package/dist/shield/shield.eip712.gen.d.ts +396 -0
- package/dist/shield/shield.eip712.gen.js +318 -0
- package/dist/shield/types.d.ts +119 -0
- package/dist/shield/types.js +4 -0
- package/dist/shield/userop/gas-estimation.d.ts +36 -0
- package/dist/shield/userop/gas-estimation.js +284 -0
- package/dist/shield/userop/index.d.ts +1 -0
- package/dist/shield/userop/index.js +1 -0
- package/dist/shield/userop/token-exchange.d.ts +54 -0
- package/dist/shield/userop/token-exchange.js +165 -0
- package/dist/shield/userop/types.d.ts +91 -0
- package/dist/shield/userop/types.js +4 -0
- package/dist/shield/userop/userOp.d.ts +26 -0
- package/dist/shield/userop/userOp.js +98 -0
- package/dist/shield/utils/chain.d.ts +2 -0
- package/dist/shield/utils/chain.js +8 -0
- package/dist/uniswap-adapter/config.d.ts +34 -0
- package/dist/uniswap-adapter/config.js +45 -0
- package/dist/uniswap-adapter/find-pools.d.ts +91 -0
- package/dist/uniswap-adapter/find-pools.js +108 -0
- package/dist/uniswap-adapter/index.d.ts +10 -0
- package/dist/uniswap-adapter/index.js +13 -0
- package/dist/uniswap-adapter/swap.d.ts +344 -0
- package/dist/uniswap-adapter/swap.js +309 -0
- package/package.json +72 -0
|
@@ -0,0 +1,423 @@
|
|
|
1
|
+
import { decodeAbiParameters, encodeAbiParameters, keccak256, toHex, } from 'viem';
|
|
2
|
+
import { bytesToHex, hexToBytes } from '../binary.js';
|
|
3
|
+
import { shieldAbiStubAbi as incoShieldAbi } from '../contracts/abi.js';
|
|
4
|
+
import { computeErc20AssetId, getAbiFromUnitFunction, } from '../contracts/utils.js';
|
|
5
|
+
import { CovalidatorError, ShieldError } from '../errors.js';
|
|
6
|
+
import { RequestDepositAttestationRequest, RequestDepositAttestationResponse, } from '../generated/inco/shield/v2/deposit_pb.js';
|
|
7
|
+
import { DraftRequest, DraftResponse, IntentKind, } from '../generated/inco/shield/v2/drafting_pb.js';
|
|
8
|
+
import { GetOwnerGenerationRequest, GetOwnerGenerationResponse, GetPermissionDetailsRequest, GetPermissionDetailsResponse, GetPermissionsByOwnerRequest, GetPermissionsBySpenderRequest, GetPermissionsResponse, RequestPermissionAttestationRequest, RequestPermissionAttestationResponse, } from '../generated/inco/shield/v2/permission_pb.js';
|
|
9
|
+
import { GetBalanceRequest, GetBalanceResponse, } from '../generated/inco/shield/v2/query_pb.js';
|
|
10
|
+
import { Address as ProtoAddress, AssetId as ProtoAssetId, } from '../generated/inco/shield/v2/types_pb.js';
|
|
11
|
+
import { parseBalance, parseOwnerGeneration, parsePermissionDetails, parsePermissions, parseUserOp07, } from './convert.js';
|
|
12
|
+
import { decryptResponse, generateRandomSalt, generateResponseKey, makeEnvelope, } from './envelope.js';
|
|
13
|
+
import { encodeIntent } from './intent.js';
|
|
14
|
+
import { balanceQueryDigest, delegatedTransferIntentDigest, delegatedWithdrawalIntentDigest, depositAttestationRequestDigest, getOwnerGenerationDigest, getPermissionDetailsDigest, getPermissionsByOwnerDigest, getPermissionsBySpenderDigest, individualRevocationIntentDigest, permissionAttestationRequestDigest, transferIntentDigest, userWideRevocationIntentDigest, withdrawalIntentDigest, } from './shield.eip712.gen.js';
|
|
15
|
+
/**
|
|
16
|
+
* `permissionId = keccak256(abi.encode(...))` over the 9 identity fields. Must
|
|
17
|
+
* match the umbo helper bit-for-bit; cross-checked in `sdk/test/permission-id.test.ts`.
|
|
18
|
+
*
|
|
19
|
+
* Off-chain only — no on-chain code recomputes this.
|
|
20
|
+
*/
|
|
21
|
+
export function computePermissionId(input) {
|
|
22
|
+
return keccak256(encodeAbiParameters([
|
|
23
|
+
{ type: 'address' }, // owner
|
|
24
|
+
{ type: 'address' }, // spender
|
|
25
|
+
{ type: 'bytes32' }, // assetId
|
|
26
|
+
{ type: 'uint256' }, // allowance
|
|
27
|
+
{ type: 'uint256' }, // start
|
|
28
|
+
{ type: 'uint256' }, // end
|
|
29
|
+
{ type: 'uint256' }, // period
|
|
30
|
+
{ type: 'bytes32' }, // agreementHash
|
|
31
|
+
{ type: 'bytes32' }, // salt
|
|
32
|
+
], [
|
|
33
|
+
input.owner,
|
|
34
|
+
input.spender,
|
|
35
|
+
input.assetId,
|
|
36
|
+
input.allowance,
|
|
37
|
+
input.start,
|
|
38
|
+
input.end,
|
|
39
|
+
input.period,
|
|
40
|
+
input.agreementHash,
|
|
41
|
+
input.salt,
|
|
42
|
+
]));
|
|
43
|
+
}
|
|
44
|
+
// ---------------------------------------------------------------------------
|
|
45
|
+
// Issue (transfer)
|
|
46
|
+
// ---------------------------------------------------------------------------
|
|
47
|
+
// TODO: replace with real gas estimation
|
|
48
|
+
// https://github.com/Inco-fhevm/shield/issues/669
|
|
49
|
+
const TODO_GAS = {
|
|
50
|
+
assetId: '0x0000000000000000000000000000000000000000000000000000000000000000',
|
|
51
|
+
maxAmount: 0n,
|
|
52
|
+
callGasLimit: 2000000n,
|
|
53
|
+
verificationGasLimit: 1000000n,
|
|
54
|
+
preVerificationGas: 100000n,
|
|
55
|
+
paymasterVerificationGasLimit: 0n,
|
|
56
|
+
paymasterPostOpGasLimit: 0n,
|
|
57
|
+
maxFeePerGas: 30000000000n, // 30 gwei
|
|
58
|
+
maxPriorityFeePerGas: 1000000000n, // 1 gwei
|
|
59
|
+
};
|
|
60
|
+
export async function issueTransfer(ctx, intentOp) {
|
|
61
|
+
const intent = {
|
|
62
|
+
kind: IntentKind.TRANSFER,
|
|
63
|
+
op: intentOp,
|
|
64
|
+
signer: ctx.signer.address,
|
|
65
|
+
gas: TODO_GAS,
|
|
66
|
+
salt: generateRandomSalt(),
|
|
67
|
+
};
|
|
68
|
+
const digest = transferIntentDigest(intent, ctx.domainSeparator);
|
|
69
|
+
const signature = await ctx.signer.sign({ hash: digest });
|
|
70
|
+
const responseKey = generateResponseKey();
|
|
71
|
+
const draftRequest = new DraftRequest({
|
|
72
|
+
intent: new Uint8Array(hexToBytes(encodeIntent(IntentKind.TRANSFER, intent))),
|
|
73
|
+
intentKind: IntentKind.TRANSFER,
|
|
74
|
+
eip712Signature: new Uint8Array(hexToBytes(signature)),
|
|
75
|
+
responseKey,
|
|
76
|
+
});
|
|
77
|
+
const envelope = await makeEnvelope(ctx.teePublicKey, draftRequest);
|
|
78
|
+
const encResponse = await ctx.rpc.draft(envelope);
|
|
79
|
+
const response = await decryptResponse(encResponse, responseKey, DraftResponse);
|
|
80
|
+
return { userOp: parseUserOp07(response.userOp) };
|
|
81
|
+
}
|
|
82
|
+
// ---------------------------------------------------------------------------
|
|
83
|
+
// IssueWithdraw
|
|
84
|
+
// ---------------------------------------------------------------------------
|
|
85
|
+
export async function issueWithdraw(ctx, intentOp) {
|
|
86
|
+
const intent = {
|
|
87
|
+
kind: IntentKind.WITHDRAW,
|
|
88
|
+
op: intentOp,
|
|
89
|
+
signer: ctx.signer.address,
|
|
90
|
+
gas: TODO_GAS,
|
|
91
|
+
salt: generateRandomSalt(),
|
|
92
|
+
};
|
|
93
|
+
const digest = withdrawalIntentDigest(intent, ctx.domainSeparator);
|
|
94
|
+
const signature = await ctx.signer.sign({ hash: digest });
|
|
95
|
+
const responseKey = generateResponseKey();
|
|
96
|
+
const draftRequest = new DraftRequest({
|
|
97
|
+
intent: new Uint8Array(hexToBytes(encodeIntent(IntentKind.WITHDRAW, intent))),
|
|
98
|
+
intentKind: IntentKind.WITHDRAW,
|
|
99
|
+
eip712Signature: new Uint8Array(hexToBytes(signature)),
|
|
100
|
+
responseKey,
|
|
101
|
+
});
|
|
102
|
+
const envelope = await makeEnvelope(ctx.teePublicKey, draftRequest);
|
|
103
|
+
const encResponse = await ctx.rpc.draft(envelope);
|
|
104
|
+
const response = await decryptResponse(encResponse, responseKey, DraftResponse);
|
|
105
|
+
return { userOp: parseUserOp07(response.userOp) };
|
|
106
|
+
}
|
|
107
|
+
// ---------------------------------------------------------------------------
|
|
108
|
+
// RequestPermissionAttestation
|
|
109
|
+
// ---------------------------------------------------------------------------
|
|
110
|
+
/**
|
|
111
|
+
* Owner-side issuance flow: sign the intent, hand it to the TEE, receive a
|
|
112
|
+
* long-lived `PermissionAttestation` for the spender. The spender presents
|
|
113
|
+
* the attestation on every subsequent draft.
|
|
114
|
+
*
|
|
115
|
+
* Doc-mandated client cross-check: recompute `permissionId` locally from
|
|
116
|
+
* intent terms and verify the TEE's returned attestation matches. A mismatch
|
|
117
|
+
* means the TEE substituted a different identity — fail closed.
|
|
118
|
+
*/
|
|
119
|
+
export async function requestPermissionAttestation(ctx, req) {
|
|
120
|
+
const { permission } = req;
|
|
121
|
+
if (ctx.signer.address.toLowerCase() !== permission.owner.toLowerCase()) {
|
|
122
|
+
throw new ShieldError({
|
|
123
|
+
message: 'requestPermissionAttestation: signer.address must match intent.owner',
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
const expectedPid = computePermissionId(permission);
|
|
127
|
+
const digest = permissionAttestationRequestDigest(req, ctx.domainSeparator);
|
|
128
|
+
const ownerSignature = await ctx.signer.sign({ hash: digest });
|
|
129
|
+
const responseKey = generateResponseKey();
|
|
130
|
+
const permissionAttestationRequestBytes = encodeAbiParameters([getAbiFromUnitFunction(incoShieldAbi, 'permissionAttestationRequest')], [req]);
|
|
131
|
+
const request = new RequestPermissionAttestationRequest({
|
|
132
|
+
permissionAttestationRequestBytes: new Uint8Array(hexToBytes(permissionAttestationRequestBytes)),
|
|
133
|
+
eip712Signature: hexToBytes(ownerSignature),
|
|
134
|
+
responseKey,
|
|
135
|
+
});
|
|
136
|
+
const envelope = await makeEnvelope(ctx.teePublicKey, request);
|
|
137
|
+
const encResponse = await ctx.rpc.requestPermissionAttestation(envelope);
|
|
138
|
+
const response = await decryptResponse(encResponse, responseKey, RequestPermissionAttestationResponse);
|
|
139
|
+
const [attestation] = decodeAbiParameters([getAbiFromUnitFunction(incoShieldAbi, 'permissionAttestation')], toHex(response.permissionAttestationBytes));
|
|
140
|
+
if (attestation.payload.permissionId !== expectedPid) {
|
|
141
|
+
throw new ShieldError({
|
|
142
|
+
message: `requestPermissionAttestation: TEE returned mismatched permissionId (expected ${expectedPid}, got ${attestation.payload.permissionId})`,
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
return attestation;
|
|
146
|
+
}
|
|
147
|
+
// ---------------------------------------------------------------------------
|
|
148
|
+
// IssueDelegatedTransfer
|
|
149
|
+
// ---------------------------------------------------------------------------
|
|
150
|
+
/**
|
|
151
|
+
* Spender-side delegated transfer draft: sign the transfer intent, present the
|
|
152
|
+
* owner's `PermissionAttestation` to the TEE, receive a spending note. The TEE
|
|
153
|
+
* verifies the attestation signature and runs all 7 validation steps before
|
|
154
|
+
* drafting the spend.
|
|
155
|
+
*/
|
|
156
|
+
export async function issueDelegatedTransfer(ctx, intentOp, attestation) {
|
|
157
|
+
const intent = {
|
|
158
|
+
kind: IntentKind.DELEGATED_TRANSFER,
|
|
159
|
+
intent: {
|
|
160
|
+
op: intentOp,
|
|
161
|
+
signer: ctx.signer.address,
|
|
162
|
+
gas: TODO_GAS,
|
|
163
|
+
salt: generateRandomSalt(),
|
|
164
|
+
},
|
|
165
|
+
spender: ctx.signer.address,
|
|
166
|
+
attestation,
|
|
167
|
+
};
|
|
168
|
+
const digest = delegatedTransferIntentDigest(intent, ctx.domainSeparator);
|
|
169
|
+
const spenderSignature = await ctx.signer.sign({ hash: digest });
|
|
170
|
+
const responseKey = generateResponseKey();
|
|
171
|
+
const draftRequest = new DraftRequest({
|
|
172
|
+
intent: new Uint8Array(hexToBytes(encodeIntent(IntentKind.DELEGATED_TRANSFER, intent))),
|
|
173
|
+
intentKind: IntentKind.DELEGATED_TRANSFER,
|
|
174
|
+
eip712Signature: new Uint8Array(hexToBytes(spenderSignature)),
|
|
175
|
+
responseKey,
|
|
176
|
+
});
|
|
177
|
+
const envelope = await makeEnvelope(ctx.teePublicKey, draftRequest);
|
|
178
|
+
const encResponse = await ctx.rpc.draft(envelope);
|
|
179
|
+
const response = await decryptResponse(encResponse, responseKey, DraftResponse);
|
|
180
|
+
return { userOp: parseUserOp07(response.userOp) };
|
|
181
|
+
}
|
|
182
|
+
// ---------------------------------------------------------------------------
|
|
183
|
+
// IssueDelegatedWithdraw
|
|
184
|
+
// ---------------------------------------------------------------------------
|
|
185
|
+
/**
|
|
186
|
+
* The resulting cheque settles byte-identically to a direct withdraw —
|
|
187
|
+
* observers cannot distinguish delegated from direct.
|
|
188
|
+
*/
|
|
189
|
+
export async function issueDelegatedWithdraw(ctx, intentOp, attestation) {
|
|
190
|
+
const intent = {
|
|
191
|
+
kind: IntentKind.DELEGATED_WITHDRAW,
|
|
192
|
+
intent: {
|
|
193
|
+
op: intentOp,
|
|
194
|
+
signer: ctx.signer.address,
|
|
195
|
+
gas: TODO_GAS,
|
|
196
|
+
salt: generateRandomSalt(),
|
|
197
|
+
},
|
|
198
|
+
spender: ctx.signer.address,
|
|
199
|
+
attestation,
|
|
200
|
+
};
|
|
201
|
+
const digest = delegatedWithdrawalIntentDigest(intent, ctx.domainSeparator);
|
|
202
|
+
const spenderSignature = await ctx.signer.sign({ hash: digest });
|
|
203
|
+
const responseKey = generateResponseKey();
|
|
204
|
+
const draftRequest = new DraftRequest({
|
|
205
|
+
intent: new Uint8Array(hexToBytes(encodeIntent(IntentKind.DELEGATED_WITHDRAW, intent))),
|
|
206
|
+
intentKind: IntentKind.DELEGATED_WITHDRAW,
|
|
207
|
+
eip712Signature: new Uint8Array(hexToBytes(spenderSignature)),
|
|
208
|
+
responseKey,
|
|
209
|
+
});
|
|
210
|
+
const envelope = await makeEnvelope(ctx.teePublicKey, draftRequest);
|
|
211
|
+
const encResponse = await ctx.rpc.draft(envelope);
|
|
212
|
+
const response = await decryptResponse(encResponse, responseKey, DraftResponse);
|
|
213
|
+
return { userOp: parseUserOp07(response.userOp) };
|
|
214
|
+
}
|
|
215
|
+
export async function revokeOne(ctx, params) {
|
|
216
|
+
const intent = {
|
|
217
|
+
kind: IntentKind.INDIVIDUAL_REVOCATION,
|
|
218
|
+
op: { permissionId: params.permissionId },
|
|
219
|
+
signer: ctx.signer.address,
|
|
220
|
+
gas: TODO_GAS,
|
|
221
|
+
salt: generateRandomSalt(),
|
|
222
|
+
};
|
|
223
|
+
const digest = individualRevocationIntentDigest(intent, ctx.domainSeparator);
|
|
224
|
+
const signature = await ctx.signer.sign({ hash: digest });
|
|
225
|
+
const responseKey = generateResponseKey();
|
|
226
|
+
const draftRequest = new DraftRequest({
|
|
227
|
+
intent: new Uint8Array(hexToBytes(encodeIntent(IntentKind.INDIVIDUAL_REVOCATION, intent))),
|
|
228
|
+
intentKind: IntentKind.INDIVIDUAL_REVOCATION,
|
|
229
|
+
eip712Signature: new Uint8Array(hexToBytes(signature)),
|
|
230
|
+
responseKey,
|
|
231
|
+
});
|
|
232
|
+
const envelope = await makeEnvelope(ctx.teePublicKey, draftRequest);
|
|
233
|
+
const encResponse = await ctx.rpc.draft(envelope);
|
|
234
|
+
const response = await decryptResponse(encResponse, responseKey, DraftResponse);
|
|
235
|
+
return { userOp: parseUserOp07(response.userOp) };
|
|
236
|
+
}
|
|
237
|
+
export async function revokeAll(ctx) {
|
|
238
|
+
const intent = {
|
|
239
|
+
kind: IntentKind.USER_WIDE_REVOCATION,
|
|
240
|
+
op: { empty: '0x' },
|
|
241
|
+
signer: ctx.signer.address,
|
|
242
|
+
gas: TODO_GAS,
|
|
243
|
+
salt: generateRandomSalt(),
|
|
244
|
+
};
|
|
245
|
+
const digest = userWideRevocationIntentDigest(intent, ctx.domainSeparator);
|
|
246
|
+
const signature = await ctx.signer.sign({ hash: digest });
|
|
247
|
+
const responseKey = generateResponseKey();
|
|
248
|
+
const draftRequest = new DraftRequest({
|
|
249
|
+
intent: new Uint8Array(hexToBytes(encodeIntent(IntentKind.USER_WIDE_REVOCATION, intent))),
|
|
250
|
+
intentKind: IntentKind.USER_WIDE_REVOCATION,
|
|
251
|
+
eip712Signature: new Uint8Array(hexToBytes(signature)),
|
|
252
|
+
responseKey,
|
|
253
|
+
});
|
|
254
|
+
const envelope = await makeEnvelope(ctx.teePublicKey, draftRequest);
|
|
255
|
+
const encResponse = await ctx.rpc.draft(envelope);
|
|
256
|
+
const response = await decryptResponse(encResponse, responseKey, DraftResponse);
|
|
257
|
+
return { userOp: parseUserOp07(response.userOp) };
|
|
258
|
+
}
|
|
259
|
+
// ---------------------------------------------------------------------------
|
|
260
|
+
// GetBalance
|
|
261
|
+
// ---------------------------------------------------------------------------
|
|
262
|
+
export async function getBalance(ctx, params) {
|
|
263
|
+
const queryTimestamp = BigInt(Math.floor(Date.now() / 1000));
|
|
264
|
+
const digest = balanceQueryDigest({
|
|
265
|
+
owner: params.address,
|
|
266
|
+
assetId: params.assetId,
|
|
267
|
+
requester: ctx.signer.address,
|
|
268
|
+
queryTimestamp,
|
|
269
|
+
}, ctx.domainSeparator);
|
|
270
|
+
const signature = await ctx.signer.sign({ hash: digest });
|
|
271
|
+
const responseKey = generateResponseKey();
|
|
272
|
+
const envelope = await makeEnvelope(ctx.teePublicKey, new GetBalanceRequest({
|
|
273
|
+
address: new ProtoAddress({ value: hexToBytes(params.address) }),
|
|
274
|
+
assetId: new ProtoAssetId({ value: hexToBytes(params.assetId) }),
|
|
275
|
+
atBlock: params.atBlock ?? 0n,
|
|
276
|
+
eip712Signature: hexToBytes(signature),
|
|
277
|
+
responseKey,
|
|
278
|
+
queryTimestamp,
|
|
279
|
+
}));
|
|
280
|
+
const response = await ctx.rpc.getBalance(envelope);
|
|
281
|
+
return parseBalance(await decryptResponse(response, responseKey, GetBalanceResponse));
|
|
282
|
+
}
|
|
283
|
+
// ---------------------------------------------------------------------------
|
|
284
|
+
// RequestDepositAttestation
|
|
285
|
+
// ---------------------------------------------------------------------------
|
|
286
|
+
export async function requestDepositAttestation(ctx, params) {
|
|
287
|
+
const depositor = ctx.signer.address;
|
|
288
|
+
const [tokenAddress] = decodeAbiParameters([{ type: 'address' }], params.assetIdentificationArgs);
|
|
289
|
+
const assetId = computeErc20AssetId(tokenAddress);
|
|
290
|
+
const digest = depositAttestationRequestDigest({
|
|
291
|
+
recipient: params.recipient,
|
|
292
|
+
assetId,
|
|
293
|
+
}, ctx.domainSeparator);
|
|
294
|
+
const signature = await ctx.signer.sign({ hash: digest });
|
|
295
|
+
const responseKey = generateResponseKey();
|
|
296
|
+
const envelope = await makeEnvelope(ctx.teePublicKey, new RequestDepositAttestationRequest({
|
|
297
|
+
recipient: new ProtoAddress({
|
|
298
|
+
value: hexToBytes(params.recipient),
|
|
299
|
+
}),
|
|
300
|
+
assetAdapter: new ProtoAddress({
|
|
301
|
+
value: hexToBytes(params.assetAdapter),
|
|
302
|
+
}),
|
|
303
|
+
assetIdentificationArgs: hexToBytes(params.assetIdentificationArgs),
|
|
304
|
+
memo: hexToBytes(params.memo),
|
|
305
|
+
escapeHatch: hexToBytes(params.escapeHatch),
|
|
306
|
+
eip712Signature: hexToBytes(signature),
|
|
307
|
+
responseKey,
|
|
308
|
+
depositor: new ProtoAddress({ value: hexToBytes(depositor) }),
|
|
309
|
+
}));
|
|
310
|
+
const response = await ctx.rpc.requestDepositAttestation(envelope);
|
|
311
|
+
const decrypted = await decryptResponse(response, responseKey, RequestDepositAttestationResponse);
|
|
312
|
+
if (decrypted.errorMessage) {
|
|
313
|
+
throw new CovalidatorError({ message: decrypted.errorMessage });
|
|
314
|
+
}
|
|
315
|
+
return {
|
|
316
|
+
toCiphertext: bytesToHex(decrypted.toCiphertext),
|
|
317
|
+
teeSignature: bytesToHex(decrypted.teeSignature),
|
|
318
|
+
};
|
|
319
|
+
}
|
|
320
|
+
// ---------------------------------------------------------------------------
|
|
321
|
+
// Permission query helpers
|
|
322
|
+
// ---------------------------------------------------------------------------
|
|
323
|
+
// Each query signs its own Solidity struct so every field is authenticated.
|
|
324
|
+
// Self-query: `requester` is always the signer.
|
|
325
|
+
async function signGetPermissionsByOwner(ctx, includeExpired) {
|
|
326
|
+
const query = {
|
|
327
|
+
requester: ctx.signer.address,
|
|
328
|
+
includeExpired,
|
|
329
|
+
timestamp: BigInt(Math.floor(Date.now() / 1000)),
|
|
330
|
+
};
|
|
331
|
+
const digest = getPermissionsByOwnerDigest(query, ctx.domainSeparator);
|
|
332
|
+
const sig = await ctx.signer.sign({ hash: digest });
|
|
333
|
+
const encodedQuery = encodeAbiParameters([getAbiFromUnitFunction(incoShieldAbi, 'getPermissionsByOwner')], [query]);
|
|
334
|
+
return { encodedQuery: hexToBytes(encodedQuery), signature: hexToBytes(sig) };
|
|
335
|
+
}
|
|
336
|
+
async function signGetPermissionsBySpender(ctx, includeExpired) {
|
|
337
|
+
const query = {
|
|
338
|
+
requester: ctx.signer.address,
|
|
339
|
+
includeExpired,
|
|
340
|
+
timestamp: BigInt(Math.floor(Date.now() / 1000)),
|
|
341
|
+
};
|
|
342
|
+
const digest = getPermissionsBySpenderDigest(query, ctx.domainSeparator);
|
|
343
|
+
const sig = await ctx.signer.sign({ hash: digest });
|
|
344
|
+
const encodedQuery = encodeAbiParameters([getAbiFromUnitFunction(incoShieldAbi, 'getPermissionsBySpender')], [query]);
|
|
345
|
+
return { encodedQuery: hexToBytes(encodedQuery), signature: hexToBytes(sig) };
|
|
346
|
+
}
|
|
347
|
+
async function signGetPermissionDetails(ctx, permissionId) {
|
|
348
|
+
const query = {
|
|
349
|
+
requester: ctx.signer.address,
|
|
350
|
+
permissionId,
|
|
351
|
+
timestamp: BigInt(Math.floor(Date.now() / 1000)),
|
|
352
|
+
};
|
|
353
|
+
const digest = getPermissionDetailsDigest(query, ctx.domainSeparator);
|
|
354
|
+
const sig = await ctx.signer.sign({ hash: digest });
|
|
355
|
+
const encodedQuery = encodeAbiParameters([getAbiFromUnitFunction(incoShieldAbi, 'getPermissionDetails')], [query]);
|
|
356
|
+
return { encodedQuery: hexToBytes(encodedQuery), signature: hexToBytes(sig) };
|
|
357
|
+
}
|
|
358
|
+
async function signGetOwnerGeneration(ctx) {
|
|
359
|
+
const query = {
|
|
360
|
+
requester: ctx.signer.address,
|
|
361
|
+
timestamp: BigInt(Math.floor(Date.now() / 1000)),
|
|
362
|
+
};
|
|
363
|
+
const digest = getOwnerGenerationDigest(query, ctx.domainSeparator);
|
|
364
|
+
const sig = await ctx.signer.sign({ hash: digest });
|
|
365
|
+
const encodedQuery = encodeAbiParameters([getAbiFromUnitFunction(incoShieldAbi, 'getOwnerGeneration')], [query]);
|
|
366
|
+
return { encodedQuery: hexToBytes(encodedQuery), signature: hexToBytes(sig) };
|
|
367
|
+
}
|
|
368
|
+
// ---------------------------------------------------------------------------
|
|
369
|
+
// GetPermissionsByOwner
|
|
370
|
+
// ---------------------------------------------------------------------------
|
|
371
|
+
export async function getPermissionsByOwner(ctx, params) {
|
|
372
|
+
const { encodedQuery, signature } = await signGetPermissionsByOwner(ctx, params.includeExpired ?? false);
|
|
373
|
+
const responseKey = generateResponseKey();
|
|
374
|
+
const envelope = await makeEnvelope(ctx.teePublicKey, new GetPermissionsByOwnerRequest({
|
|
375
|
+
getPermissionsByOwnerBytes: encodedQuery,
|
|
376
|
+
eip712Signature: signature,
|
|
377
|
+
responseKey,
|
|
378
|
+
}));
|
|
379
|
+
const response = await ctx.rpc.getPermissionsByOwner(envelope);
|
|
380
|
+
return parsePermissions(await decryptResponse(response, responseKey, GetPermissionsResponse));
|
|
381
|
+
}
|
|
382
|
+
// ---------------------------------------------------------------------------
|
|
383
|
+
// GetPermissionsBySpender
|
|
384
|
+
// ---------------------------------------------------------------------------
|
|
385
|
+
export async function getPermissionsBySpender(ctx, params) {
|
|
386
|
+
const { encodedQuery, signature } = await signGetPermissionsBySpender(ctx, params.includeExpired ?? false);
|
|
387
|
+
const responseKey = generateResponseKey();
|
|
388
|
+
const envelope = await makeEnvelope(ctx.teePublicKey, new GetPermissionsBySpenderRequest({
|
|
389
|
+
getPermissionsBySpenderBytes: encodedQuery,
|
|
390
|
+
eip712Signature: signature,
|
|
391
|
+
responseKey,
|
|
392
|
+
}));
|
|
393
|
+
const response = await ctx.rpc.getPermissionsBySpender(envelope);
|
|
394
|
+
return parsePermissions(await decryptResponse(response, responseKey, GetPermissionsResponse));
|
|
395
|
+
}
|
|
396
|
+
// ---------------------------------------------------------------------------
|
|
397
|
+
// GetPermissionDetails
|
|
398
|
+
// ---------------------------------------------------------------------------
|
|
399
|
+
export async function getPermissionDetails(ctx, params) {
|
|
400
|
+
const { encodedQuery, signature } = await signGetPermissionDetails(ctx, params.permissionId);
|
|
401
|
+
const responseKey = generateResponseKey();
|
|
402
|
+
const envelope = await makeEnvelope(ctx.teePublicKey, new GetPermissionDetailsRequest({
|
|
403
|
+
getPermissionDetailsBytes: encodedQuery,
|
|
404
|
+
eip712Signature: signature,
|
|
405
|
+
responseKey,
|
|
406
|
+
}));
|
|
407
|
+
const response = await ctx.rpc.getPermissionDetails(envelope);
|
|
408
|
+
return parsePermissionDetails(await decryptResponse(response, responseKey, GetPermissionDetailsResponse));
|
|
409
|
+
}
|
|
410
|
+
// ---------------------------------------------------------------------------
|
|
411
|
+
// GetOwnerGeneration
|
|
412
|
+
// ---------------------------------------------------------------------------
|
|
413
|
+
export async function getOwnerGeneration(ctx) {
|
|
414
|
+
const { encodedQuery, signature } = await signGetOwnerGeneration(ctx);
|
|
415
|
+
const responseKey = generateResponseKey();
|
|
416
|
+
const envelope = await makeEnvelope(ctx.teePublicKey, new GetOwnerGenerationRequest({
|
|
417
|
+
getOwnerGenerationBytes: encodedQuery,
|
|
418
|
+
eip712Signature: signature,
|
|
419
|
+
responseKey,
|
|
420
|
+
}));
|
|
421
|
+
const response = await ctx.rpc.getOwnerGeneration(envelope);
|
|
422
|
+
return parseOwnerGeneration(await decryptResponse(response, responseKey, GetOwnerGenerationResponse));
|
|
423
|
+
}
|