@chipi-stack/chipi-react 14.9.0 → 14.10.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/README.md +33 -0
- package/dist/hooks.d.mts +2 -1
- package/dist/hooks.d.ts +2 -1
- package/dist/hooks.js +1032 -4
- package/dist/hooks.js.map +1 -1
- package/dist/hooks.mjs +1029 -6
- package/dist/hooks.mjs.map +1 -1
- package/dist/{index-B8e6TdyG.d.mts → index-D9-uVlda.d.mts} +119 -1
- package/dist/{index-B8e6TdyG.d.ts → index-D9-uVlda.d.ts} +119 -1
- package/dist/index.d.mts +3 -2
- package/dist/index.d.ts +3 -2
- package/dist/index.js +1032 -4
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1029 -6
- package/dist/index.mjs.map +1 -1
- package/package.json +5 -5
package/dist/hooks.mjs
CHANGED
|
@@ -6,7 +6,7 @@ import 'react/jsx-runtime';
|
|
|
6
6
|
import { ChipiApiError } from '@chipi-stack/shared';
|
|
7
7
|
import { OnChainTxStatus, Chain, ChainToken } from '@chipi-stack/types';
|
|
8
8
|
import * as nc from 'crypto';
|
|
9
|
-
import { buildX402TypedData } from '@chipi-stack/core';
|
|
9
|
+
import { buildX402TypedData, derivePoolKeypair, deriveCompanionKeypair, deriveCompanionAddress, getPrivateBalance, requestGasFunding, waitForFunding, GAS_FUND_STRK, execShield, sweepCompanion, execUnshield, ChipiProofProvider } from '@chipi-stack/core';
|
|
10
10
|
|
|
11
11
|
var __defProp = Object.defineProperty;
|
|
12
12
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
@@ -10664,6 +10664,7 @@ var OutsideExecutionTypesV2 = {
|
|
|
10664
10664
|
]
|
|
10665
10665
|
};
|
|
10666
10666
|
var OutsideExecutionVersion = {
|
|
10667
|
+
UNSUPPORTED: "0",
|
|
10667
10668
|
V1: "1",
|
|
10668
10669
|
V2: "2"
|
|
10669
10670
|
};
|
|
@@ -18555,9 +18556,76 @@ var BrotherId = class _BrotherId {
|
|
|
18555
18556
|
}
|
|
18556
18557
|
}
|
|
18557
18558
|
};
|
|
18558
|
-
|
|
18559
|
-
}
|
|
18559
|
+
var RpcProvider2 = class extends Mixin(RpcProvider, StarknetId, BrotherId) {
|
|
18560
|
+
};
|
|
18560
18561
|
new RpcProvider({ default: true });
|
|
18562
|
+
var Signer = class {
|
|
18563
|
+
constructor(pk = utils.randomPrivateKey()) {
|
|
18564
|
+
__publicField(this, "pk");
|
|
18565
|
+
this.pk = pk instanceof Uint8Array ? buf2hex(pk) : toHex(pk);
|
|
18566
|
+
}
|
|
18567
|
+
async getPubKey() {
|
|
18568
|
+
return getStarkKey(this.pk);
|
|
18569
|
+
}
|
|
18570
|
+
async signMessage(typedData, accountAddress) {
|
|
18571
|
+
const msgHash = getMessageHash(typedData, accountAddress);
|
|
18572
|
+
return this.signRaw(msgHash);
|
|
18573
|
+
}
|
|
18574
|
+
async signTransaction(transactions, details) {
|
|
18575
|
+
const compiledCalldata = getExecuteCalldata(transactions, details.cairoVersion);
|
|
18576
|
+
let msgHash;
|
|
18577
|
+
if (Object.values(api_exports3.ETransactionVersion3).includes(details.version)) {
|
|
18578
|
+
const det = details;
|
|
18579
|
+
msgHash = calculateInvokeTransactionHash2({
|
|
18580
|
+
...det,
|
|
18581
|
+
senderAddress: det.walletAddress,
|
|
18582
|
+
compiledCalldata,
|
|
18583
|
+
version: det.version,
|
|
18584
|
+
nonceDataAvailabilityMode: intDAM(det.nonceDataAvailabilityMode),
|
|
18585
|
+
feeDataAvailabilityMode: intDAM(det.feeDataAvailabilityMode)
|
|
18586
|
+
});
|
|
18587
|
+
} else {
|
|
18588
|
+
throw Error("unsupported signTransaction version");
|
|
18589
|
+
}
|
|
18590
|
+
return this.signRaw(msgHash);
|
|
18591
|
+
}
|
|
18592
|
+
async signDeployAccountTransaction(details) {
|
|
18593
|
+
const compiledConstructorCalldata = CallData.compile(details.constructorCalldata);
|
|
18594
|
+
let msgHash;
|
|
18595
|
+
if (Object.values(api_exports3.ETransactionVersion3).includes(details.version)) {
|
|
18596
|
+
const det = details;
|
|
18597
|
+
msgHash = calculateDeployAccountTransactionHash3({
|
|
18598
|
+
...det,
|
|
18599
|
+
salt: det.addressSalt,
|
|
18600
|
+
compiledConstructorCalldata,
|
|
18601
|
+
version: det.version,
|
|
18602
|
+
nonceDataAvailabilityMode: intDAM(det.nonceDataAvailabilityMode),
|
|
18603
|
+
feeDataAvailabilityMode: intDAM(det.feeDataAvailabilityMode)
|
|
18604
|
+
});
|
|
18605
|
+
} else {
|
|
18606
|
+
throw Error("unsupported signDeployAccountTransaction version");
|
|
18607
|
+
}
|
|
18608
|
+
return this.signRaw(msgHash);
|
|
18609
|
+
}
|
|
18610
|
+
async signDeclareTransaction(details) {
|
|
18611
|
+
let msgHash;
|
|
18612
|
+
if (Object.values(api_exports3.ETransactionVersion3).includes(details.version)) {
|
|
18613
|
+
const det = details;
|
|
18614
|
+
msgHash = calculateDeclareTransactionHash3({
|
|
18615
|
+
...det,
|
|
18616
|
+
version: det.version,
|
|
18617
|
+
nonceDataAvailabilityMode: intDAM(det.nonceDataAvailabilityMode),
|
|
18618
|
+
feeDataAvailabilityMode: intDAM(det.feeDataAvailabilityMode)
|
|
18619
|
+
});
|
|
18620
|
+
} else {
|
|
18621
|
+
throw Error("unsupported signDeclareTransaction version");
|
|
18622
|
+
}
|
|
18623
|
+
return this.signRaw(msgHash);
|
|
18624
|
+
}
|
|
18625
|
+
async signRaw(msgHash) {
|
|
18626
|
+
return sign(msgHash, this.pk);
|
|
18627
|
+
}
|
|
18628
|
+
};
|
|
18561
18629
|
var uint256_exports = {};
|
|
18562
18630
|
__export2(uint256_exports, {
|
|
18563
18631
|
bnToUint256: () => bnToUint256,
|
|
@@ -19002,7 +19070,7 @@ var PaymasterRpc = class _PaymasterRpc {
|
|
|
19002
19070
|
);
|
|
19003
19071
|
}
|
|
19004
19072
|
};
|
|
19005
|
-
new PaymasterRpc({ default: true });
|
|
19073
|
+
var defaultPaymaster = new PaymasterRpc({ default: true });
|
|
19006
19074
|
var Deployer = class {
|
|
19007
19075
|
constructor(address, entryPoint) {
|
|
19008
19076
|
__publicField(this, "address");
|
|
@@ -19077,8 +19145,791 @@ var Deployer = class {
|
|
|
19077
19145
|
};
|
|
19078
19146
|
}
|
|
19079
19147
|
};
|
|
19080
|
-
new Deployer(UDC.ADDRESS, UDC.ENTRYPOINT);
|
|
19148
|
+
var defaultDeployer = new Deployer(UDC.ADDRESS, UDC.ENTRYPOINT);
|
|
19081
19149
|
new Deployer(LegacyUDC.ADDRESS, LegacyUDC.ENTRYPOINT);
|
|
19150
|
+
var Account = class extends RpcProvider2 {
|
|
19151
|
+
constructor(options) {
|
|
19152
|
+
const {
|
|
19153
|
+
provider,
|
|
19154
|
+
address,
|
|
19155
|
+
signer,
|
|
19156
|
+
cairoVersion,
|
|
19157
|
+
transactionVersion,
|
|
19158
|
+
paymaster,
|
|
19159
|
+
defaultTipType
|
|
19160
|
+
} = options;
|
|
19161
|
+
super(provider);
|
|
19162
|
+
__publicField(this, "signer");
|
|
19163
|
+
__publicField(this, "address");
|
|
19164
|
+
__publicField(this, "cairoVersion");
|
|
19165
|
+
__publicField(this, "transactionVersion");
|
|
19166
|
+
__publicField(this, "paymaster");
|
|
19167
|
+
__publicField(this, "deployer");
|
|
19168
|
+
__publicField(this, "defaultTipType");
|
|
19169
|
+
__publicField(this, "deploySelf", this.deployAccount);
|
|
19170
|
+
this.address = address.toLowerCase();
|
|
19171
|
+
this.signer = isString(signer) || signer instanceof Uint8Array ? new Signer(signer) : signer;
|
|
19172
|
+
if (cairoVersion) {
|
|
19173
|
+
this.cairoVersion = cairoVersion.toString();
|
|
19174
|
+
}
|
|
19175
|
+
this.transactionVersion = transactionVersion ?? config2.get("transactionVersion");
|
|
19176
|
+
this.paymaster = paymaster ? new PaymasterRpc(paymaster) : defaultPaymaster;
|
|
19177
|
+
this.deployer = options.deployer ?? defaultDeployer;
|
|
19178
|
+
this.defaultTipType = defaultTipType ?? config2.get("defaultTipType");
|
|
19179
|
+
logger.debug("Account setup", {
|
|
19180
|
+
transactionVersion: this.transactionVersion,
|
|
19181
|
+
cairoVersion: this.cairoVersion,
|
|
19182
|
+
channel: this.channel.id
|
|
19183
|
+
});
|
|
19184
|
+
}
|
|
19185
|
+
/** @deprecated @hidden */
|
|
19186
|
+
// The deprecation tag is meant to discourage use, not to signal future removal
|
|
19187
|
+
// it should only be removed if the relationship with the corresponding Provider.create(...) method changes
|
|
19188
|
+
static async create() {
|
|
19189
|
+
throw new LibraryError("Not supported");
|
|
19190
|
+
}
|
|
19191
|
+
async getNonce(blockIdentifier) {
|
|
19192
|
+
return super.getNonceForAddress(this.address, blockIdentifier);
|
|
19193
|
+
}
|
|
19194
|
+
async getNonceSafe(nonce) {
|
|
19195
|
+
try {
|
|
19196
|
+
return toBigInt(nonce ?? await this.getNonce());
|
|
19197
|
+
} catch (error) {
|
|
19198
|
+
return 0n;
|
|
19199
|
+
}
|
|
19200
|
+
}
|
|
19201
|
+
/**
|
|
19202
|
+
* Retrieves the Cairo version from the network and sets `cairoVersion` if not already set in the constructor.
|
|
19203
|
+
* @param classHash if provided detects Cairo version from classHash, otherwise from the account address
|
|
19204
|
+
*/
|
|
19205
|
+
async getCairoVersion(classHash) {
|
|
19206
|
+
if (!this.cairoVersion) {
|
|
19207
|
+
const { cairo } = classHash ? await super.getContractVersion(void 0, classHash) : await super.getContractVersion(this.address);
|
|
19208
|
+
this.cairoVersion = cairo;
|
|
19209
|
+
}
|
|
19210
|
+
return this.cairoVersion;
|
|
19211
|
+
}
|
|
19212
|
+
// TODO: TT Cairo version is still needed for invoke on existing contracts
|
|
19213
|
+
async estimateInvokeFee(calls, details = {}) {
|
|
19214
|
+
const invocations = [{ type: api_exports3.ETransactionType.INVOKE, payload: [calls].flat() }];
|
|
19215
|
+
const estimateBulk = await this.estimateFeeBulk(invocations, details);
|
|
19216
|
+
return estimateBulk[0];
|
|
19217
|
+
}
|
|
19218
|
+
async estimateDeclareFee(payload, details = {}) {
|
|
19219
|
+
assert(
|
|
19220
|
+
isSierra(payload.contract),
|
|
19221
|
+
"Declare fee estimation is not supported for Cairo0 contracts"
|
|
19222
|
+
);
|
|
19223
|
+
const invocations = [
|
|
19224
|
+
{
|
|
19225
|
+
type: api_exports3.ETransactionType.DECLARE,
|
|
19226
|
+
payload: extractContractHashes(payload, await this.channel.getStarknetVersion())
|
|
19227
|
+
}
|
|
19228
|
+
];
|
|
19229
|
+
const estimateBulk = await this.estimateFeeBulk(invocations, details);
|
|
19230
|
+
return estimateBulk[0];
|
|
19231
|
+
}
|
|
19232
|
+
async estimateAccountDeployFee({
|
|
19233
|
+
classHash,
|
|
19234
|
+
addressSalt = 0,
|
|
19235
|
+
constructorCalldata = [],
|
|
19236
|
+
contractAddress
|
|
19237
|
+
}, details = {}) {
|
|
19238
|
+
const compiledCalldata = CallData.compile(constructorCalldata);
|
|
19239
|
+
const contractAddressFinal = contractAddress ?? calculateContractAddressFromHash(addressSalt, classHash, compiledCalldata, 0);
|
|
19240
|
+
const invocations = [
|
|
19241
|
+
{
|
|
19242
|
+
type: api_exports3.ETransactionType.DEPLOY_ACCOUNT,
|
|
19243
|
+
payload: {
|
|
19244
|
+
classHash,
|
|
19245
|
+
constructorCalldata: compiledCalldata,
|
|
19246
|
+
addressSalt,
|
|
19247
|
+
contractAddress: contractAddressFinal
|
|
19248
|
+
}
|
|
19249
|
+
}
|
|
19250
|
+
];
|
|
19251
|
+
const estimateBulk = await this.estimateFeeBulk(invocations, details);
|
|
19252
|
+
return estimateBulk[0];
|
|
19253
|
+
}
|
|
19254
|
+
async estimateDeployFee(payload, details = {}) {
|
|
19255
|
+
const { calls } = this.deployer.buildDeployerCall(payload, this.address);
|
|
19256
|
+
return this.estimateInvokeFee(calls, details);
|
|
19257
|
+
}
|
|
19258
|
+
async estimateFeeBulk(invocations, details = {}) {
|
|
19259
|
+
if (!invocations.length) throw TypeError("Invocations should be non-empty array");
|
|
19260
|
+
if (details.resourceBounds)
|
|
19261
|
+
return [resourceBoundsToEstimateFeeResponse(details.resourceBounds)];
|
|
19262
|
+
const { nonce, blockIdentifier, version, skipValidate } = details;
|
|
19263
|
+
const detailsWithTip = await this.resolveDetailsWithTip(details);
|
|
19264
|
+
const accountInvocations = await this.accountInvocationsFactory(invocations, {
|
|
19265
|
+
...v3Details(detailsWithTip),
|
|
19266
|
+
versions: [
|
|
19267
|
+
toTransactionVersion(
|
|
19268
|
+
toFeeVersion(this.transactionVersion) || ETransactionVersion33.F3,
|
|
19269
|
+
version
|
|
19270
|
+
)
|
|
19271
|
+
// sierra
|
|
19272
|
+
],
|
|
19273
|
+
nonce,
|
|
19274
|
+
blockIdentifier,
|
|
19275
|
+
skipValidate
|
|
19276
|
+
});
|
|
19277
|
+
return super.getEstimateFeeBulk(accountInvocations, {
|
|
19278
|
+
blockIdentifier,
|
|
19279
|
+
skipValidate
|
|
19280
|
+
});
|
|
19281
|
+
}
|
|
19282
|
+
async simulateTransaction(invocations, details = {}) {
|
|
19283
|
+
if (!invocations.length) throw TypeError("Invocations should be non-empty array");
|
|
19284
|
+
const {
|
|
19285
|
+
nonce,
|
|
19286
|
+
blockIdentifier,
|
|
19287
|
+
skipValidate = true,
|
|
19288
|
+
skipExecute,
|
|
19289
|
+
version: providedVersion
|
|
19290
|
+
} = details;
|
|
19291
|
+
const detailsWithTip = await this.resolveDetailsWithTip(details);
|
|
19292
|
+
const accountInvocations = await this.accountInvocationsFactory(invocations, {
|
|
19293
|
+
...v3Details(detailsWithTip),
|
|
19294
|
+
versions: [this.resolveTransactionVersion(providedVersion)],
|
|
19295
|
+
nonce,
|
|
19296
|
+
blockIdentifier,
|
|
19297
|
+
skipValidate
|
|
19298
|
+
});
|
|
19299
|
+
return super.getSimulateTransaction(accountInvocations, {
|
|
19300
|
+
blockIdentifier,
|
|
19301
|
+
skipValidate,
|
|
19302
|
+
skipExecute
|
|
19303
|
+
});
|
|
19304
|
+
}
|
|
19305
|
+
async execute(transactions, transactionsDetail = {}) {
|
|
19306
|
+
const calls = [transactions].flat();
|
|
19307
|
+
const detailsWithTip = await this.resolveDetailsWithTip(transactionsDetail);
|
|
19308
|
+
const { resourceBounds: providedResourceBounds } = transactionsDetail;
|
|
19309
|
+
let resourceBounds = providedResourceBounds;
|
|
19310
|
+
if (!resourceBounds) {
|
|
19311
|
+
const estimateResponse = await this.estimateInvokeFee(calls, detailsWithTip);
|
|
19312
|
+
resourceBounds = estimateResponse.resourceBounds;
|
|
19313
|
+
}
|
|
19314
|
+
const accountInvocations = await this.accountInvocationsFactory(
|
|
19315
|
+
[{ type: api_exports3.ETransactionType.INVOKE, payload: calls }],
|
|
19316
|
+
{
|
|
19317
|
+
...v3Details(detailsWithTip),
|
|
19318
|
+
resourceBounds,
|
|
19319
|
+
versions: [this.resolveTransactionVersion(transactionsDetail.version)],
|
|
19320
|
+
nonce: transactionsDetail.nonce,
|
|
19321
|
+
skipValidate: false
|
|
19322
|
+
}
|
|
19323
|
+
);
|
|
19324
|
+
const invocation = accountInvocations[0];
|
|
19325
|
+
return this.invokeFunction(
|
|
19326
|
+
{
|
|
19327
|
+
contractAddress: invocation.contractAddress,
|
|
19328
|
+
calldata: invocation.calldata,
|
|
19329
|
+
signature: invocation.signature
|
|
19330
|
+
},
|
|
19331
|
+
{
|
|
19332
|
+
...v3Details(detailsWithTip),
|
|
19333
|
+
resourceBounds: invocation.resourceBounds,
|
|
19334
|
+
nonce: invocation.nonce,
|
|
19335
|
+
version: invocation.version
|
|
19336
|
+
}
|
|
19337
|
+
);
|
|
19338
|
+
}
|
|
19339
|
+
/**
|
|
19340
|
+
* Execute one or multiple calls through the account contract,
|
|
19341
|
+
* responding as soon as a new transaction is possible with the same account.
|
|
19342
|
+
* Useful for gaming usage.
|
|
19343
|
+
* - This method requires the provider to be initialized with `pre_confirmed` blockIdentifier option.
|
|
19344
|
+
* - Rpc 0.9 minimum.
|
|
19345
|
+
* - In a normal myAccount.execute() call, followed by myProvider.waitForTransaction(), you have an immediate access to the events and to the transaction report. Here, we are processing consecutive transactions faster, but events & transaction reports are not available immediately.
|
|
19346
|
+
* - As a consequence of the previous point, do not use contract/account deployment with this method.
|
|
19347
|
+
* @param {AllowArray<Call>} transactions - Single call or array of calls to execute
|
|
19348
|
+
* @param {UniversalDetails} [transactionsDetail] - Transaction execution options
|
|
19349
|
+
* @param {fastWaitForTransactionOptions} [waitDetail={retries: 50, retryInterval: 500}] - options to scan the network for the next possible transaction. `retries` is the number of times to retry, `retryInterval` is the time in ms between retries.
|
|
19350
|
+
* @returns {Promise<fastExecuteResponse>} Response containing the transaction result and status for the next transaction. If `isReady` is true, you can execute the next transaction. If false, timeout has been reached before the next transaction was possible.
|
|
19351
|
+
* @example
|
|
19352
|
+
* ```typescript
|
|
19353
|
+
* const myProvider = new RpcProvider({ nodeUrl: url, blockIdentifier: BlockTag.PRE_CONFIRMED });
|
|
19354
|
+
* const myAccount = new Account({ provider: myProvider, address: accountAddress0, signer: privateKey0 });
|
|
19355
|
+
* const resp = await myAccount.fastExecute(
|
|
19356
|
+
* call, { tip: recommendedTip},
|
|
19357
|
+
* { retries: 30, retryInterval: 500 });
|
|
19358
|
+
* // if resp.isReady is true, you can launch immediately a new tx.
|
|
19359
|
+
* ```
|
|
19360
|
+
*/
|
|
19361
|
+
async fastExecute(transactions, transactionsDetail = {}, waitDetail = {}) {
|
|
19362
|
+
assert(
|
|
19363
|
+
this.channel.blockIdentifier === BlockTag.PRE_CONFIRMED,
|
|
19364
|
+
"Provider needs to be initialized with `pre_confirmed` blockIdentifier option."
|
|
19365
|
+
);
|
|
19366
|
+
const initNonce = BigInt(
|
|
19367
|
+
transactionsDetail.nonce ?? await this.getNonceForAddress(this.address, BlockTag.PRE_CONFIRMED)
|
|
19368
|
+
);
|
|
19369
|
+
const details = { ...transactionsDetail, nonce: initNonce };
|
|
19370
|
+
const resultTx = await this.execute(transactions, details);
|
|
19371
|
+
const resultWait = await this.fastWaitForTransaction(
|
|
19372
|
+
resultTx.transaction_hash,
|
|
19373
|
+
this.address,
|
|
19374
|
+
initNonce,
|
|
19375
|
+
waitDetail
|
|
19376
|
+
);
|
|
19377
|
+
return { txResult: resultTx, isReady: resultWait };
|
|
19378
|
+
}
|
|
19379
|
+
/**
|
|
19380
|
+
* First check if contract is already declared, if not declare it
|
|
19381
|
+
* If contract already declared returned transaction_hash is ''.
|
|
19382
|
+
* Method will pass even if contract is already declared
|
|
19383
|
+
* @param transactionsDetail (optional)
|
|
19384
|
+
*/
|
|
19385
|
+
async declareIfNot(payload, transactionsDetail = {}) {
|
|
19386
|
+
const declareContractPayload = extractContractHashes(
|
|
19387
|
+
payload,
|
|
19388
|
+
await this.channel.getStarknetVersion()
|
|
19389
|
+
);
|
|
19390
|
+
try {
|
|
19391
|
+
await this.getClassByHash(declareContractPayload.classHash);
|
|
19392
|
+
} catch (error) {
|
|
19393
|
+
return this.declare(payload, transactionsDetail);
|
|
19394
|
+
}
|
|
19395
|
+
return {
|
|
19396
|
+
transaction_hash: "",
|
|
19397
|
+
class_hash: declareContractPayload.classHash
|
|
19398
|
+
};
|
|
19399
|
+
}
|
|
19400
|
+
async declare(payload, details = {}) {
|
|
19401
|
+
assert(isSierra(payload.contract), SYSTEM_MESSAGES.declareNonSierra);
|
|
19402
|
+
const declareContractPayload = extractContractHashes(
|
|
19403
|
+
payload,
|
|
19404
|
+
await this.channel.getStarknetVersion()
|
|
19405
|
+
);
|
|
19406
|
+
const detailsWithTip = await this.resolveDetailsWithTip(details);
|
|
19407
|
+
const { resourceBounds: providedResourceBounds } = details;
|
|
19408
|
+
let resourceBounds = providedResourceBounds;
|
|
19409
|
+
if (!resourceBounds) {
|
|
19410
|
+
const estimateResponse = await this.estimateDeclareFee(payload, detailsWithTip);
|
|
19411
|
+
resourceBounds = estimateResponse.resourceBounds;
|
|
19412
|
+
}
|
|
19413
|
+
const accountInvocations = await this.accountInvocationsFactory(
|
|
19414
|
+
[{ type: api_exports3.ETransactionType.DECLARE, payload: declareContractPayload }],
|
|
19415
|
+
{
|
|
19416
|
+
...v3Details(detailsWithTip),
|
|
19417
|
+
resourceBounds,
|
|
19418
|
+
versions: [this.resolveTransactionVersion(details.version)],
|
|
19419
|
+
nonce: details.nonce,
|
|
19420
|
+
skipValidate: false
|
|
19421
|
+
}
|
|
19422
|
+
);
|
|
19423
|
+
const declaration = accountInvocations[0];
|
|
19424
|
+
return super.declareContract(
|
|
19425
|
+
{
|
|
19426
|
+
senderAddress: declaration.senderAddress,
|
|
19427
|
+
signature: declaration.signature,
|
|
19428
|
+
contract: declaration.contract,
|
|
19429
|
+
compiledClassHash: declaration.compiledClassHash
|
|
19430
|
+
},
|
|
19431
|
+
{
|
|
19432
|
+
...v3Details(detailsWithTip),
|
|
19433
|
+
nonce: declaration.nonce,
|
|
19434
|
+
resourceBounds: declaration.resourceBounds,
|
|
19435
|
+
version: declaration.version
|
|
19436
|
+
}
|
|
19437
|
+
);
|
|
19438
|
+
}
|
|
19439
|
+
async deploy(payload, details = {}) {
|
|
19440
|
+
const { calls, addresses } = this.deployer.buildDeployerCall(payload, this.address);
|
|
19441
|
+
const invokeResponse = await this.execute(calls, details);
|
|
19442
|
+
return {
|
|
19443
|
+
...invokeResponse,
|
|
19444
|
+
contract_address: addresses
|
|
19445
|
+
};
|
|
19446
|
+
}
|
|
19447
|
+
async deployContract(payload, details = {}) {
|
|
19448
|
+
const deployTx = await this.deploy(payload, details);
|
|
19449
|
+
const txReceipt = await this.waitForTransaction(deployTx.transaction_hash, details);
|
|
19450
|
+
return this.deployer.parseDeployerEvent(
|
|
19451
|
+
txReceipt
|
|
19452
|
+
);
|
|
19453
|
+
}
|
|
19454
|
+
async declareAndDeploy(payload, details = {}) {
|
|
19455
|
+
let declare = await this.declareIfNot(payload, details);
|
|
19456
|
+
if (declare.transaction_hash !== "") {
|
|
19457
|
+
const tx = await this.waitForTransaction(declare.transaction_hash, details);
|
|
19458
|
+
declare = { ...declare, ...tx };
|
|
19459
|
+
}
|
|
19460
|
+
const deploy = await this.deployContract(
|
|
19461
|
+
{ ...payload, classHash: declare.class_hash },
|
|
19462
|
+
details
|
|
19463
|
+
);
|
|
19464
|
+
return { declare: { ...declare }, deploy };
|
|
19465
|
+
}
|
|
19466
|
+
async deployAccount({
|
|
19467
|
+
classHash,
|
|
19468
|
+
constructorCalldata = [],
|
|
19469
|
+
addressSalt = 0,
|
|
19470
|
+
contractAddress: providedContractAddress
|
|
19471
|
+
}, details = {}) {
|
|
19472
|
+
const compiledCalldata = CallData.compile(constructorCalldata);
|
|
19473
|
+
const contractAddress = providedContractAddress ?? calculateContractAddressFromHash(addressSalt, classHash, compiledCalldata, 0);
|
|
19474
|
+
const detailsWithTip = await this.resolveDetailsWithTip(details);
|
|
19475
|
+
const { resourceBounds: providedResourceBounds } = details;
|
|
19476
|
+
let resourceBounds = providedResourceBounds;
|
|
19477
|
+
if (!resourceBounds) {
|
|
19478
|
+
const estimateResponse = await this.estimateAccountDeployFee(
|
|
19479
|
+
{
|
|
19480
|
+
classHash,
|
|
19481
|
+
constructorCalldata,
|
|
19482
|
+
addressSalt,
|
|
19483
|
+
contractAddress
|
|
19484
|
+
},
|
|
19485
|
+
detailsWithTip
|
|
19486
|
+
);
|
|
19487
|
+
resourceBounds = estimateResponse.resourceBounds;
|
|
19488
|
+
}
|
|
19489
|
+
const accountInvocations = await this.accountInvocationsFactory(
|
|
19490
|
+
[
|
|
19491
|
+
{
|
|
19492
|
+
type: api_exports3.ETransactionType.DEPLOY_ACCOUNT,
|
|
19493
|
+
payload: {
|
|
19494
|
+
classHash,
|
|
19495
|
+
constructorCalldata: compiledCalldata,
|
|
19496
|
+
addressSalt,
|
|
19497
|
+
contractAddress
|
|
19498
|
+
}
|
|
19499
|
+
}
|
|
19500
|
+
],
|
|
19501
|
+
{
|
|
19502
|
+
...v3Details(detailsWithTip),
|
|
19503
|
+
resourceBounds,
|
|
19504
|
+
versions: [this.resolveTransactionVersion(details.version)],
|
|
19505
|
+
nonce: ZERO,
|
|
19506
|
+
// DEPLOY_ACCOUNT always uses nonce 0
|
|
19507
|
+
skipValidate: false
|
|
19508
|
+
}
|
|
19509
|
+
);
|
|
19510
|
+
const deployment = accountInvocations[0];
|
|
19511
|
+
return super.deployAccountContract(
|
|
19512
|
+
{
|
|
19513
|
+
classHash: deployment.classHash,
|
|
19514
|
+
addressSalt: deployment.addressSalt,
|
|
19515
|
+
constructorCalldata: deployment.constructorCalldata,
|
|
19516
|
+
signature: deployment.signature
|
|
19517
|
+
},
|
|
19518
|
+
{
|
|
19519
|
+
...v3Details(detailsWithTip),
|
|
19520
|
+
nonce: deployment.nonce,
|
|
19521
|
+
resourceBounds: deployment.resourceBounds,
|
|
19522
|
+
version: deployment.version
|
|
19523
|
+
}
|
|
19524
|
+
);
|
|
19525
|
+
}
|
|
19526
|
+
async signMessage(typedData) {
|
|
19527
|
+
return this.signer.signMessage(typedData, this.address);
|
|
19528
|
+
}
|
|
19529
|
+
async hashMessage(typedData) {
|
|
19530
|
+
return getMessageHash(typedData, this.address);
|
|
19531
|
+
}
|
|
19532
|
+
/**
|
|
19533
|
+
* Verify if an account is compatible with SNIP-9 outside execution, and with which version of this standard.
|
|
19534
|
+
* @returns {OutsideExecutionVersion} Not compatible, V1, V2.
|
|
19535
|
+
* @example
|
|
19536
|
+
* ```typescript
|
|
19537
|
+
* const result = myAccount.getSnip9Version();
|
|
19538
|
+
* // result = "V1"
|
|
19539
|
+
* ```
|
|
19540
|
+
*/
|
|
19541
|
+
async getSnip9Version() {
|
|
19542
|
+
if (await supportsInterface(this, this.address, SNIP9_V2_INTERFACE_ID)) {
|
|
19543
|
+
return OutsideExecutionVersion.V2;
|
|
19544
|
+
}
|
|
19545
|
+
if (await supportsInterface(this, this.address, SNIP9_V1_INTERFACE_ID)) {
|
|
19546
|
+
return OutsideExecutionVersion.V1;
|
|
19547
|
+
}
|
|
19548
|
+
return OutsideExecutionVersion.UNSUPPORTED;
|
|
19549
|
+
}
|
|
19550
|
+
/**
|
|
19551
|
+
* Verify if a SNIP-9 nonce has not yet been used by the account.
|
|
19552
|
+
* @param {BigNumberish} nonce SNIP-9 nonce to test.
|
|
19553
|
+
* @returns {boolean} true if SNIP-9 nonce not yet used.
|
|
19554
|
+
* @example
|
|
19555
|
+
* ```typescript
|
|
19556
|
+
* const result = myAccount.isValidSnip9Nonce(1234);
|
|
19557
|
+
* // result = true
|
|
19558
|
+
* ```
|
|
19559
|
+
*/
|
|
19560
|
+
async isValidSnip9Nonce(nonce) {
|
|
19561
|
+
try {
|
|
19562
|
+
const call = {
|
|
19563
|
+
contractAddress: this.address,
|
|
19564
|
+
entrypoint: "is_valid_outside_execution_nonce",
|
|
19565
|
+
calldata: [toHex(nonce)]
|
|
19566
|
+
};
|
|
19567
|
+
const resp = await this.callContract(call);
|
|
19568
|
+
return BigInt(resp[0]) !== 0n;
|
|
19569
|
+
} catch (error) {
|
|
19570
|
+
throw new Error(`Failed to check if nonce is valid: ${error}`);
|
|
19571
|
+
}
|
|
19572
|
+
}
|
|
19573
|
+
/**
|
|
19574
|
+
* Outside transaction needs a specific SNIP-9 nonce, that we get in this function.
|
|
19575
|
+
* A SNIP-9 nonce can be any number not yet used ; no ordering is needed.
|
|
19576
|
+
* @returns {string} an Hex string of a SNIP-9 nonce.
|
|
19577
|
+
* @example
|
|
19578
|
+
* ```typescript
|
|
19579
|
+
* const result = myAccount.getSnip9Nonce();
|
|
19580
|
+
* // result = "0x28a612590dbc36927933c8ee0f357eee639c8b22b3d3aa86949eed3ada4ac55"
|
|
19581
|
+
* ```
|
|
19582
|
+
*/
|
|
19583
|
+
async getSnip9Nonce() {
|
|
19584
|
+
const nonce = randomAddress();
|
|
19585
|
+
const isValidNonce = await this.isValidSnip9Nonce(nonce);
|
|
19586
|
+
if (!isValidNonce) {
|
|
19587
|
+
return this.getSnip9Nonce();
|
|
19588
|
+
}
|
|
19589
|
+
return nonce;
|
|
19590
|
+
}
|
|
19591
|
+
/**
|
|
19592
|
+
* Creates an object containing transaction(s) that can be executed by an other account with` Account.executeFromOutside()`, called Outside Transaction.
|
|
19593
|
+
* @param {OutsideExecutionOptions} options Parameters of the transaction(s).
|
|
19594
|
+
* @param {AllowArray<Call>} calls Transaction(s) to execute.
|
|
19595
|
+
* @param {OutsideExecutionVersion} [version] SNIP-9 version of the Account that creates the outside transaction.
|
|
19596
|
+
* @param {BigNumberish} [nonce] Outside Nonce.
|
|
19597
|
+
* @returns {OutsideTransaction} and object that can be used in `Account.executeFromOutside()`
|
|
19598
|
+
* @example
|
|
19599
|
+
* ```typescript
|
|
19600
|
+
* const now_seconds = Math.floor(Date.now() / 1000);
|
|
19601
|
+
* const callOptions: OutsideExecutionOptions = {
|
|
19602
|
+
caller: executorAccount.address, execute_after: now_seconds - 3600, execute_before: now_seconds + 3600 };
|
|
19603
|
+
* const call1: Call = { contractAddress: ethAddress, entrypoint: 'transfer', calldata: {
|
|
19604
|
+
* recipient: recipientAccount.address, amount: cairo.uint256(100) } };
|
|
19605
|
+
* const outsideTransaction1: OutsideTransaction = await signerAccount.getOutsideTransaction(callOptions, call3);
|
|
19606
|
+
* // result = {
|
|
19607
|
+
* // outsideExecution: {
|
|
19608
|
+
* // caller: '0x64b48806902a367c8598f4f95c305e8c1a1acba5f082d294a43793113115691',
|
|
19609
|
+
* // nonce: '0x28a612590dbc36927933c8ee0f357eee639c8b22b3d3aa86949eed3ada4ac55',
|
|
19610
|
+
* // execute_after: 1723650229, execute_before: 1723704229, calls: [[Object]] },
|
|
19611
|
+
* // signature: Signature {
|
|
19612
|
+
* // r: 67518627037915514985321278857825384106482999609634873287406612756843916814n,
|
|
19613
|
+
* // s: 737198738569840639192844101690009498983611654458636624293579534560862067709n, recovery: 0 },
|
|
19614
|
+
* // signerAddress: '0x655f8fd7c4013c07cf12a92184aa6c314d181443913e21f7e209a18f0c78492',
|
|
19615
|
+
* // version: '2'
|
|
19616
|
+
* // }
|
|
19617
|
+
* ```
|
|
19618
|
+
*/
|
|
19619
|
+
async getOutsideTransaction(options, calls, version, nonce) {
|
|
19620
|
+
if (!isHex2(options.caller) && options.caller !== "ANY_CALLER") {
|
|
19621
|
+
throw new Error(`The caller ${options.caller} is not valid.`);
|
|
19622
|
+
}
|
|
19623
|
+
const codedCaller = isHex2(options.caller) ? options.caller : OutsideExecutionCallerAny;
|
|
19624
|
+
const myCalls = [calls].flat();
|
|
19625
|
+
const supportedVersion = version ?? await this.getSnip9Version();
|
|
19626
|
+
if (!supportedVersion) {
|
|
19627
|
+
throw new Error("This account is not handling outside transactions.");
|
|
19628
|
+
}
|
|
19629
|
+
const myNonce = nonce ? toHex(nonce) : await this.getSnip9Nonce();
|
|
19630
|
+
const message = getTypedData(
|
|
19631
|
+
await this.getChainId(),
|
|
19632
|
+
{
|
|
19633
|
+
caller: codedCaller,
|
|
19634
|
+
execute_after: options.execute_after,
|
|
19635
|
+
execute_before: options.execute_before
|
|
19636
|
+
},
|
|
19637
|
+
myNonce,
|
|
19638
|
+
myCalls,
|
|
19639
|
+
supportedVersion
|
|
19640
|
+
);
|
|
19641
|
+
const sign2 = await this.signMessage(message);
|
|
19642
|
+
const toExecute = {
|
|
19643
|
+
caller: codedCaller,
|
|
19644
|
+
nonce: myNonce,
|
|
19645
|
+
execute_after: options.execute_after,
|
|
19646
|
+
execute_before: options.execute_before,
|
|
19647
|
+
calls: myCalls.map(getOutsideCall)
|
|
19648
|
+
};
|
|
19649
|
+
return {
|
|
19650
|
+
outsideExecution: toExecute,
|
|
19651
|
+
signature: sign2,
|
|
19652
|
+
signerAddress: this.address,
|
|
19653
|
+
version: supportedVersion
|
|
19654
|
+
};
|
|
19655
|
+
}
|
|
19656
|
+
/**
|
|
19657
|
+
* An account B executes a transaction that has been signed by an account A.
|
|
19658
|
+
* Fees are paid by B.
|
|
19659
|
+
* @param {AllowArray<OutsideTransaction>} outsideTransaction the signed transaction generated by `Account.getOutsideTransaction()`.
|
|
19660
|
+
* @param {UniversalDetails} [opts] same options than `Account.execute()`.
|
|
19661
|
+
* @returns {InvokeFunctionResponse} same response than `Account.execute()`.
|
|
19662
|
+
* @example
|
|
19663
|
+
* ```typescript
|
|
19664
|
+
* const outsideTransaction1: OutsideTransaction = await signerAccount.getOutsideTransaction(callOptions, call1);
|
|
19665
|
+
* const outsideTransaction2: OutsideTransaction = await signerAccount.getOutsideTransaction(callOptions4, call4);
|
|
19666
|
+
* const result = await myAccount.executeFromOutside([
|
|
19667
|
+
outsideTransaction1,
|
|
19668
|
+
outsideTransaction2,
|
|
19669
|
+
]);
|
|
19670
|
+
* // result = { transaction_hash: '0x11233...`}
|
|
19671
|
+
* ```
|
|
19672
|
+
*/
|
|
19673
|
+
async executeFromOutside(outsideTransaction, opts) {
|
|
19674
|
+
const multiCall = buildExecuteFromOutsideCall(outsideTransaction);
|
|
19675
|
+
return this.execute(multiCall, opts);
|
|
19676
|
+
}
|
|
19677
|
+
/*
|
|
19678
|
+
* Support methods
|
|
19679
|
+
*/
|
|
19680
|
+
/**
|
|
19681
|
+
* Helper method to resolve details with tip estimation
|
|
19682
|
+
* @private
|
|
19683
|
+
*/
|
|
19684
|
+
async resolveDetailsWithTip(details) {
|
|
19685
|
+
return {
|
|
19686
|
+
...details,
|
|
19687
|
+
tip: details.tip ?? (await this.getEstimateTip())[this.defaultTipType]
|
|
19688
|
+
};
|
|
19689
|
+
}
|
|
19690
|
+
/**
|
|
19691
|
+
* Helper method to resolve transaction version
|
|
19692
|
+
* @private
|
|
19693
|
+
*/
|
|
19694
|
+
resolveTransactionVersion(providedVersion) {
|
|
19695
|
+
return toTransactionVersion(
|
|
19696
|
+
this.transactionVersion || ETransactionVersion33.V3,
|
|
19697
|
+
providedVersion
|
|
19698
|
+
);
|
|
19699
|
+
}
|
|
19700
|
+
async buildInvocation(call, details) {
|
|
19701
|
+
const calldata = getExecuteCalldata(call, await this.getCairoVersion());
|
|
19702
|
+
const signature = !details.skipValidate ? await this.signer.signTransaction(call, details) : [];
|
|
19703
|
+
return {
|
|
19704
|
+
...v3Details(details),
|
|
19705
|
+
contractAddress: this.address,
|
|
19706
|
+
calldata,
|
|
19707
|
+
signature
|
|
19708
|
+
};
|
|
19709
|
+
}
|
|
19710
|
+
async buildDeclarePayload(payload, details) {
|
|
19711
|
+
const { classHash, contract, compiledClassHash } = extractContractHashes(
|
|
19712
|
+
payload,
|
|
19713
|
+
await this.channel.getStarknetVersion()
|
|
19714
|
+
);
|
|
19715
|
+
const compressedCompiledContract = parseContract(contract);
|
|
19716
|
+
assert(
|
|
19717
|
+
!isUndefined(compiledClassHash) && (details.version === ETransactionVersion33.F3 || details.version === ETransactionVersion33.V3),
|
|
19718
|
+
"V3 Transaction work with Cairo1 Contracts and require compiledClassHash"
|
|
19719
|
+
);
|
|
19720
|
+
const signature = !details.skipValidate ? await this.signer.signDeclareTransaction({
|
|
19721
|
+
...details,
|
|
19722
|
+
...v3Details(details),
|
|
19723
|
+
classHash,
|
|
19724
|
+
compiledClassHash,
|
|
19725
|
+
senderAddress: details.walletAddress
|
|
19726
|
+
}) : [];
|
|
19727
|
+
return {
|
|
19728
|
+
senderAddress: details.walletAddress,
|
|
19729
|
+
signature,
|
|
19730
|
+
contract: compressedCompiledContract,
|
|
19731
|
+
compiledClassHash
|
|
19732
|
+
};
|
|
19733
|
+
}
|
|
19734
|
+
async buildAccountDeployPayload({
|
|
19735
|
+
classHash,
|
|
19736
|
+
addressSalt = 0,
|
|
19737
|
+
constructorCalldata = [],
|
|
19738
|
+
contractAddress: providedContractAddress
|
|
19739
|
+
}, details) {
|
|
19740
|
+
const compiledCalldata = CallData.compile(constructorCalldata);
|
|
19741
|
+
const contractAddress = providedContractAddress ?? calculateContractAddressFromHash(addressSalt, classHash, compiledCalldata, 0);
|
|
19742
|
+
const signature = !details.skipValidate ? await this.signer.signDeployAccountTransaction({
|
|
19743
|
+
...details,
|
|
19744
|
+
...v3Details(details),
|
|
19745
|
+
classHash,
|
|
19746
|
+
contractAddress,
|
|
19747
|
+
addressSalt,
|
|
19748
|
+
constructorCalldata: compiledCalldata
|
|
19749
|
+
}) : [];
|
|
19750
|
+
return {
|
|
19751
|
+
...v3Details(details),
|
|
19752
|
+
classHash,
|
|
19753
|
+
addressSalt,
|
|
19754
|
+
constructorCalldata: compiledCalldata,
|
|
19755
|
+
signature
|
|
19756
|
+
};
|
|
19757
|
+
}
|
|
19758
|
+
async accountInvocationsFactory(invocations, details) {
|
|
19759
|
+
const { nonce, blockIdentifier, skipValidate = true } = details;
|
|
19760
|
+
const safeNonce = await this.getNonceSafe(nonce);
|
|
19761
|
+
const chainId = await this.getChainId();
|
|
19762
|
+
const versions = details.versions.map((it) => toTransactionVersion(it));
|
|
19763
|
+
const tx0Payload = "payload" in invocations[0] ? invocations[0].payload : invocations[0];
|
|
19764
|
+
const cairoVersion = invocations[0].type === api_exports3.ETransactionType.DEPLOY_ACCOUNT ? await this.getCairoVersion(tx0Payload.classHash) : await this.getCairoVersion();
|
|
19765
|
+
return Promise.all(
|
|
19766
|
+
[].concat(invocations).map(async (transaction, index) => {
|
|
19767
|
+
const txPayload = "payload" in transaction ? transaction.payload : transaction;
|
|
19768
|
+
const signerDetails = {
|
|
19769
|
+
...v3Details(details),
|
|
19770
|
+
walletAddress: this.address,
|
|
19771
|
+
nonce: toBigInt(Number(safeNonce) + index),
|
|
19772
|
+
chainId,
|
|
19773
|
+
cairoVersion,
|
|
19774
|
+
version: versions[0],
|
|
19775
|
+
skipValidate
|
|
19776
|
+
};
|
|
19777
|
+
const common2 = {
|
|
19778
|
+
type: transaction.type,
|
|
19779
|
+
nonce: toBigInt(Number(safeNonce) + index),
|
|
19780
|
+
blockIdentifier,
|
|
19781
|
+
version: versions[0]
|
|
19782
|
+
};
|
|
19783
|
+
if (transaction.type === api_exports3.ETransactionType.INVOKE) {
|
|
19784
|
+
const payload = await this.buildInvocation(
|
|
19785
|
+
[].concat(txPayload),
|
|
19786
|
+
signerDetails
|
|
19787
|
+
);
|
|
19788
|
+
return {
|
|
19789
|
+
...common2,
|
|
19790
|
+
...payload,
|
|
19791
|
+
...signerDetails
|
|
19792
|
+
};
|
|
19793
|
+
}
|
|
19794
|
+
if (transaction.type === api_exports3.ETransactionType.DEPLOY) {
|
|
19795
|
+
const { calls } = this.deployer.buildDeployerCall(txPayload, this.address);
|
|
19796
|
+
const payload = await this.buildInvocation(calls, signerDetails);
|
|
19797
|
+
return {
|
|
19798
|
+
...common2,
|
|
19799
|
+
...payload,
|
|
19800
|
+
...signerDetails,
|
|
19801
|
+
type: api_exports3.ETransactionType.INVOKE
|
|
19802
|
+
};
|
|
19803
|
+
}
|
|
19804
|
+
if (transaction.type === api_exports3.ETransactionType.DECLARE) {
|
|
19805
|
+
assert(
|
|
19806
|
+
isSierra(txPayload.contract),
|
|
19807
|
+
"Declare fee estimation is not supported for Cairo0 contracts"
|
|
19808
|
+
);
|
|
19809
|
+
const payload = await this.buildDeclarePayload(txPayload, signerDetails);
|
|
19810
|
+
return {
|
|
19811
|
+
...common2,
|
|
19812
|
+
...payload,
|
|
19813
|
+
...signerDetails
|
|
19814
|
+
};
|
|
19815
|
+
}
|
|
19816
|
+
if (transaction.type === api_exports3.ETransactionType.DEPLOY_ACCOUNT) {
|
|
19817
|
+
const payload = await this.buildAccountDeployPayload(txPayload, signerDetails);
|
|
19818
|
+
return {
|
|
19819
|
+
...common2,
|
|
19820
|
+
...payload,
|
|
19821
|
+
...signerDetails
|
|
19822
|
+
};
|
|
19823
|
+
}
|
|
19824
|
+
throw Error(`accountInvocationsFactory: unsupported transaction type: ${transaction}`);
|
|
19825
|
+
})
|
|
19826
|
+
);
|
|
19827
|
+
}
|
|
19828
|
+
/*
|
|
19829
|
+
* SNIP-29 Paymaster
|
|
19830
|
+
*/
|
|
19831
|
+
async buildPaymasterTransaction(calls, paymasterDetails) {
|
|
19832
|
+
if (!paymasterDetails.deploymentData) {
|
|
19833
|
+
const snip9Version = await this.getSnip9Version();
|
|
19834
|
+
if (snip9Version === OutsideExecutionVersion.UNSUPPORTED) {
|
|
19835
|
+
throw Error("Account is not compatible with SNIP-9");
|
|
19836
|
+
}
|
|
19837
|
+
}
|
|
19838
|
+
const parameters = {
|
|
19839
|
+
version: "0x1",
|
|
19840
|
+
feeMode: paymasterDetails.feeMode,
|
|
19841
|
+
timeBounds: paymasterDetails.timeBounds
|
|
19842
|
+
};
|
|
19843
|
+
let transaction;
|
|
19844
|
+
if (paymasterDetails.deploymentData) {
|
|
19845
|
+
if (calls.length > 0) {
|
|
19846
|
+
transaction = {
|
|
19847
|
+
type: "deploy_and_invoke",
|
|
19848
|
+
invoke: { userAddress: this.address, calls },
|
|
19849
|
+
deployment: paymasterDetails.deploymentData
|
|
19850
|
+
};
|
|
19851
|
+
} else {
|
|
19852
|
+
transaction = {
|
|
19853
|
+
type: "deploy",
|
|
19854
|
+
deployment: paymasterDetails.deploymentData
|
|
19855
|
+
};
|
|
19856
|
+
}
|
|
19857
|
+
} else {
|
|
19858
|
+
transaction = {
|
|
19859
|
+
type: "invoke",
|
|
19860
|
+
invoke: { userAddress: this.address, calls }
|
|
19861
|
+
};
|
|
19862
|
+
}
|
|
19863
|
+
return this.paymaster.buildTransaction(transaction, parameters);
|
|
19864
|
+
}
|
|
19865
|
+
async estimatePaymasterTransactionFee(calls, paymasterDetails) {
|
|
19866
|
+
const preparedTransaction = await this.buildPaymasterTransaction(calls, paymasterDetails);
|
|
19867
|
+
return preparedTransaction.fee;
|
|
19868
|
+
}
|
|
19869
|
+
async preparePaymasterTransaction(preparedTransaction) {
|
|
19870
|
+
let transaction;
|
|
19871
|
+
switch (preparedTransaction.type) {
|
|
19872
|
+
case "deploy_and_invoke": {
|
|
19873
|
+
const signature = await this.signMessage(preparedTransaction.typed_data);
|
|
19874
|
+
transaction = {
|
|
19875
|
+
type: "deploy_and_invoke",
|
|
19876
|
+
invoke: {
|
|
19877
|
+
userAddress: this.address,
|
|
19878
|
+
typedData: preparedTransaction.typed_data,
|
|
19879
|
+
signature: signatureToHexArray(signature)
|
|
19880
|
+
},
|
|
19881
|
+
deployment: preparedTransaction.deployment
|
|
19882
|
+
};
|
|
19883
|
+
break;
|
|
19884
|
+
}
|
|
19885
|
+
case "invoke": {
|
|
19886
|
+
const signature = await this.signMessage(preparedTransaction.typed_data);
|
|
19887
|
+
transaction = {
|
|
19888
|
+
type: "invoke",
|
|
19889
|
+
invoke: {
|
|
19890
|
+
userAddress: this.address,
|
|
19891
|
+
typedData: preparedTransaction.typed_data,
|
|
19892
|
+
signature: signatureToHexArray(signature)
|
|
19893
|
+
}
|
|
19894
|
+
};
|
|
19895
|
+
break;
|
|
19896
|
+
}
|
|
19897
|
+
case "deploy": {
|
|
19898
|
+
transaction = {
|
|
19899
|
+
type: "deploy",
|
|
19900
|
+
deployment: preparedTransaction.deployment
|
|
19901
|
+
};
|
|
19902
|
+
break;
|
|
19903
|
+
}
|
|
19904
|
+
default:
|
|
19905
|
+
throw Error("Invalid transaction type");
|
|
19906
|
+
}
|
|
19907
|
+
return transaction;
|
|
19908
|
+
}
|
|
19909
|
+
async executePaymasterTransaction(calls, paymasterDetails, maxFeeInGasToken) {
|
|
19910
|
+
const preparedTransaction = await this.buildPaymasterTransaction(calls, paymasterDetails);
|
|
19911
|
+
assertPaymasterTransactionSafety(
|
|
19912
|
+
preparedTransaction,
|
|
19913
|
+
calls,
|
|
19914
|
+
paymasterDetails,
|
|
19915
|
+
maxFeeInGasToken
|
|
19916
|
+
);
|
|
19917
|
+
const transaction = await this.preparePaymasterTransaction(preparedTransaction);
|
|
19918
|
+
return this.paymaster.executeTransaction(transaction, preparedTransaction.parameters).then((response) => ({ transaction_hash: response.transaction_hash }));
|
|
19919
|
+
}
|
|
19920
|
+
/*
|
|
19921
|
+
* External methods
|
|
19922
|
+
*/
|
|
19923
|
+
/**
|
|
19924
|
+
* Get the Starknet ID for an address
|
|
19925
|
+
* @param address - The address to get the Starknet ID for
|
|
19926
|
+
* @param StarknetIdContract - The Starknet ID contract address (optional)
|
|
19927
|
+
* @returns The Starknet ID for the address
|
|
19928
|
+
*/
|
|
19929
|
+
async getStarkName(address = this.address, StarknetIdContract2) {
|
|
19930
|
+
return super.getStarkName(address, StarknetIdContract2);
|
|
19931
|
+
}
|
|
19932
|
+
};
|
|
19082
19933
|
var connect_exports = {};
|
|
19083
19934
|
__export2(connect_exports, {
|
|
19084
19935
|
addDeclareTransaction: () => addDeclareTransaction,
|
|
@@ -20004,6 +20855,178 @@ function useThresholdSign(opts) {
|
|
|
20004
20855
|
finalize
|
|
20005
20856
|
};
|
|
20006
20857
|
}
|
|
20858
|
+
var DEFAULTS = {
|
|
20859
|
+
apiBaseUrl: "https://api.chipipay.com/v1",
|
|
20860
|
+
rpcUrl: "https://api.cartridge.gg/x/starknet/mainnet",
|
|
20861
|
+
chainId: "0x534e5f4d41494e",
|
|
20862
|
+
gasTankAddress: "0x232f9c4ec684c03caae94f75987ea0540c06173d96dd5c6705521eb45e28b0a"
|
|
20863
|
+
};
|
|
20864
|
+
async function derivePrivacyAccount(p) {
|
|
20865
|
+
const pool = await derivePoolKeypair({
|
|
20866
|
+
anchorSecret: p.anchorSecret,
|
|
20867
|
+
seedDomainTag: p.seedDomainTag
|
|
20868
|
+
});
|
|
20869
|
+
const companion = await deriveCompanionKeypair(p.anchorSecret);
|
|
20870
|
+
return {
|
|
20871
|
+
companionAddress: deriveCompanionAddress({
|
|
20872
|
+
publicKey: companion.publicKey,
|
|
20873
|
+
classHash: p.classHash
|
|
20874
|
+
}),
|
|
20875
|
+
companionKey: companion.privateKey,
|
|
20876
|
+
classHash: p.classHash,
|
|
20877
|
+
poolKey: BigInt(pool.privateKey)
|
|
20878
|
+
};
|
|
20879
|
+
}
|
|
20880
|
+
function buildCtx(config3, keys) {
|
|
20881
|
+
const rpcUrl = config3.rpcUrl ?? DEFAULTS.rpcUrl;
|
|
20882
|
+
return {
|
|
20883
|
+
provider: new RpcProvider2({ nodeUrl: rpcUrl }),
|
|
20884
|
+
chainId: config3.chainId ?? DEFAULTS.chainId,
|
|
20885
|
+
companionAddress: keys.companionAddress,
|
|
20886
|
+
companionKey: keys.companionKey,
|
|
20887
|
+
classHash: keys.classHash,
|
|
20888
|
+
poolKey: keys.poolKey,
|
|
20889
|
+
provingProvider: new ChipiProofProvider({
|
|
20890
|
+
baseUrl: config3.apiBaseUrl ?? DEFAULTS.apiBaseUrl,
|
|
20891
|
+
apiKey: config3.apiPublicKey,
|
|
20892
|
+
getBearerToken: config3.getBearerToken,
|
|
20893
|
+
chainId: config3.chainId ?? DEFAULTS.chainId
|
|
20894
|
+
}),
|
|
20895
|
+
gatewaySubmitUrl: config3.gatewaySubmitUrl,
|
|
20896
|
+
rpcUrl
|
|
20897
|
+
};
|
|
20898
|
+
}
|
|
20899
|
+
async function runShield(input) {
|
|
20900
|
+
const { config: config3, keys } = input;
|
|
20901
|
+
const ctx = buildCtx(config3, keys);
|
|
20902
|
+
input.onStep?.("prepare");
|
|
20903
|
+
input.onStep?.("fund");
|
|
20904
|
+
await requestGasFunding(keys.companionAddress, {
|
|
20905
|
+
baseUrl: config3.apiBaseUrl ?? DEFAULTS.apiBaseUrl,
|
|
20906
|
+
apiKey: config3.apiPublicKey,
|
|
20907
|
+
getBearerToken: config3.getBearerToken
|
|
20908
|
+
});
|
|
20909
|
+
if (input.fundDeposit) {
|
|
20910
|
+
input.onStep?.("deposit");
|
|
20911
|
+
await input.fundDeposit(keys.companionAddress, input.amount);
|
|
20912
|
+
}
|
|
20913
|
+
await waitForFunding(ctx.provider, keys.companionAddress, {
|
|
20914
|
+
strk: GAS_FUND_STRK,
|
|
20915
|
+
token: input.fundDeposit ? { address: input.token, amount: input.amount } : void 0
|
|
20916
|
+
});
|
|
20917
|
+
input.onStep?.("prove");
|
|
20918
|
+
const result = await execShield(ctx, input.token, input.amount);
|
|
20919
|
+
input.onStep?.("finish");
|
|
20920
|
+
void sweepCompanion({
|
|
20921
|
+
provider: ctx.provider,
|
|
20922
|
+
companionAddress: keys.companionAddress,
|
|
20923
|
+
companionKey: keys.companionKey,
|
|
20924
|
+
gasTank: config3.gasTankAddress ?? DEFAULTS.gasTankAddress
|
|
20925
|
+
});
|
|
20926
|
+
return result;
|
|
20927
|
+
}
|
|
20928
|
+
async function runUnshield(input) {
|
|
20929
|
+
const { config: config3, keys } = input;
|
|
20930
|
+
const ctx = buildCtx(config3, keys);
|
|
20931
|
+
input.onStep?.("prepare");
|
|
20932
|
+
input.onStep?.("fund");
|
|
20933
|
+
await requestGasFunding(keys.companionAddress, {
|
|
20934
|
+
baseUrl: config3.apiBaseUrl ?? DEFAULTS.apiBaseUrl,
|
|
20935
|
+
apiKey: config3.apiPublicKey,
|
|
20936
|
+
getBearerToken: config3.getBearerToken
|
|
20937
|
+
});
|
|
20938
|
+
await waitForFunding(ctx.provider, keys.companionAddress, { strk: GAS_FUND_STRK });
|
|
20939
|
+
input.onStep?.("prove");
|
|
20940
|
+
const result = await execUnshield(ctx, input.token, input.amount);
|
|
20941
|
+
input.onStep?.("finish");
|
|
20942
|
+
const swept = await sweepCompanion({
|
|
20943
|
+
provider: ctx.provider,
|
|
20944
|
+
companionAddress: keys.companionAddress,
|
|
20945
|
+
companionKey: keys.companionKey,
|
|
20946
|
+
gasTank: config3.gasTankAddress ?? DEFAULTS.gasTankAddress,
|
|
20947
|
+
deliverToken: { address: input.token, to: input.deliverTo },
|
|
20948
|
+
strict: true
|
|
20949
|
+
});
|
|
20950
|
+
if (swept.transactionHash === null) {
|
|
20951
|
+
throw new Error(
|
|
20952
|
+
"unshield_undelivered: the withdrawal settled but delivery to your wallet could not be confirmed \u2014 funds are safe in the companion account; retry"
|
|
20953
|
+
);
|
|
20954
|
+
}
|
|
20955
|
+
return result;
|
|
20956
|
+
}
|
|
20957
|
+
function useShield() {
|
|
20958
|
+
const mutation = useMutation({ mutationFn: runShield });
|
|
20959
|
+
return {
|
|
20960
|
+
shield: mutation.mutate,
|
|
20961
|
+
shieldAsync: mutation.mutateAsync,
|
|
20962
|
+
data: mutation.data,
|
|
20963
|
+
isLoading: mutation.isPending,
|
|
20964
|
+
isError: mutation.isError,
|
|
20965
|
+
error: mutation.error,
|
|
20966
|
+
isSuccess: mutation.isSuccess,
|
|
20967
|
+
reset: mutation.reset
|
|
20968
|
+
};
|
|
20969
|
+
}
|
|
20970
|
+
function useUnshield() {
|
|
20971
|
+
const mutation = useMutation({
|
|
20972
|
+
mutationFn: runUnshield
|
|
20973
|
+
});
|
|
20974
|
+
return {
|
|
20975
|
+
unshield: mutation.mutate,
|
|
20976
|
+
unshieldAsync: mutation.mutateAsync,
|
|
20977
|
+
data: mutation.data,
|
|
20978
|
+
isLoading: mutation.isPending,
|
|
20979
|
+
isError: mutation.isError,
|
|
20980
|
+
error: mutation.error,
|
|
20981
|
+
isSuccess: mutation.isSuccess,
|
|
20982
|
+
reset: mutation.reset
|
|
20983
|
+
};
|
|
20984
|
+
}
|
|
20985
|
+
function netPrivateBalance(events) {
|
|
20986
|
+
const byToken = {};
|
|
20987
|
+
for (const e of events) {
|
|
20988
|
+
const signed = e.direction === "shield" ? e.amount : -e.amount;
|
|
20989
|
+
byToken[e.token] = (byToken[e.token] ?? 0n) + signed;
|
|
20990
|
+
}
|
|
20991
|
+
for (const k of Object.keys(byToken)) if (byToken[k] < 0n) byToken[k] = 0n;
|
|
20992
|
+
return byToken;
|
|
20993
|
+
}
|
|
20994
|
+
function usePrivateBalance(input) {
|
|
20995
|
+
const query = useQuery({
|
|
20996
|
+
queryKey: [
|
|
20997
|
+
"chipi-private-balance",
|
|
20998
|
+
input.mode,
|
|
20999
|
+
// A stale cache here is a stale MONEY balance (review finding m1):
|
|
21000
|
+
// ledger mode keys on a content digest (length alone missed same-count
|
|
21001
|
+
// edits); onchain mode keys on the account AND the token filter.
|
|
21002
|
+
input.mode === "ledger" ? input.events.reduce((h, e) => h + (e.direction === "shield" ? e.amount : -e.amount), 0n).toString() + ":" + input.events.length : input.keys.companionAddress + ":" + (input.tokens ?? []).join(",")
|
|
21003
|
+
],
|
|
21004
|
+
queryFn: async () => {
|
|
21005
|
+
if (input.mode === "ledger") return netPrivateBalance(input.events);
|
|
21006
|
+
const ctx = buildCtx(input.config, input.keys);
|
|
21007
|
+
const { byToken } = await getPrivateBalance({
|
|
21008
|
+
provider: ctx.provider,
|
|
21009
|
+
account: new Account({
|
|
21010
|
+
provider: ctx.provider,
|
|
21011
|
+
address: input.keys.companionAddress,
|
|
21012
|
+
signer: input.keys.companionKey,
|
|
21013
|
+
cairoVersion: "1"
|
|
21014
|
+
}),
|
|
21015
|
+
viewingKey: input.keys.poolKey,
|
|
21016
|
+
provingProvider: ctx.provingProvider,
|
|
21017
|
+
tokens: input.tokens
|
|
21018
|
+
});
|
|
21019
|
+
return byToken;
|
|
21020
|
+
}
|
|
21021
|
+
});
|
|
21022
|
+
return {
|
|
21023
|
+
byToken: query.data ?? {},
|
|
21024
|
+
isLoading: query.isLoading,
|
|
21025
|
+
isError: query.isError,
|
|
21026
|
+
error: query.error,
|
|
21027
|
+
refetch: query.refetch
|
|
21028
|
+
};
|
|
21029
|
+
}
|
|
20007
21030
|
/*! Bundled license information:
|
|
20008
21031
|
|
|
20009
21032
|
@scure/base/lib/esm/index.js:
|
|
@@ -20028,6 +21051,6 @@ pako/dist/pako.esm.mjs:
|
|
|
20028
21051
|
(*! pako 2.1.0 https://github.com/nodeca/pako @license (MIT AND Zlib) *)
|
|
20029
21052
|
*/
|
|
20030
21053
|
|
|
20031
|
-
export { useAddSessionKeyToContract, useApprove, useCallAnyContract, useChipiSession, useChipiWallet, useChipiWalletObject, useCreateSessionKey, useCreateWallet, useExecuteWithSession, useGetSessionData, useGetSku, useGetSkuList, useGetSkuPurchase, useGetTokenBalance, useGetTransaction, useGetTransactionList, useGetTransactionStatus, useGetWallet, useGuardianRecovery, useMigrateWalletToPasskey, useMigrateWalletToShhh, usePurchaseSku, useRecordSendTransaction, useRevokeSessionKey, useShhhSigner, useSignTypedData, useSyncOnChainTransfers, useThresholdSign, useTransfer, useUpdateWalletEncryption, useX402Payment };
|
|
21054
|
+
export { derivePrivacyAccount, netPrivateBalance, useAddSessionKeyToContract, useApprove, useCallAnyContract, useChipiSession, useChipiWallet, useChipiWalletObject, useCreateSessionKey, useCreateWallet, useExecuteWithSession, useGetSessionData, useGetSku, useGetSkuList, useGetSkuPurchase, useGetTokenBalance, useGetTransaction, useGetTransactionList, useGetTransactionStatus, useGetWallet, useGuardianRecovery, useMigrateWalletToPasskey, useMigrateWalletToShhh, usePrivateBalance, usePurchaseSku, useRecordSendTransaction, useRevokeSessionKey, useShhhSigner, useShield, useSignTypedData, useSyncOnChainTransfers, useThresholdSign, useTransfer, useUnshield, useUpdateWalletEncryption, useX402Payment };
|
|
20032
21055
|
//# sourceMappingURL=hooks.mjs.map
|
|
20033
21056
|
//# sourceMappingURL=hooks.mjs.map
|