starknet 10.6.7 → 10.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/dist/index.d.ts +64 -36
- package/dist/index.global.js +111 -36
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +111 -36
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +111 -36
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
package/dist/index.mjs
CHANGED
|
@@ -7292,6 +7292,8 @@ var Subscription = class {
|
|
|
7292
7292
|
maxBufferSize;
|
|
7293
7293
|
handler = null;
|
|
7294
7294
|
_isClosed = false;
|
|
7295
|
+
// The unsubscribe request currently on the wire, shared by concurrent callers.
|
|
7296
|
+
pendingUnsubscribe = null;
|
|
7295
7297
|
/**
|
|
7296
7298
|
* @internal
|
|
7297
7299
|
* @param options - Subscription configuration options
|
|
@@ -7310,6 +7312,20 @@ var Subscription = class {
|
|
|
7310
7312
|
get isClosed() {
|
|
7311
7313
|
return this._isClosed;
|
|
7312
7314
|
}
|
|
7315
|
+
/**
|
|
7316
|
+
* Closes the subscription locally, without contacting the node.
|
|
7317
|
+
*
|
|
7318
|
+
* Used when the channel knows the subscription is gone and cannot be recovered — a
|
|
7319
|
+
* re-subscribe refused after a reconnection, for instance. Without it the object would keep
|
|
7320
|
+
* reporting itself as open while no event could ever reach its handler again.
|
|
7321
|
+
* @internal
|
|
7322
|
+
*/
|
|
7323
|
+
_markClosed() {
|
|
7324
|
+
if (this._isClosed) return;
|
|
7325
|
+
this._isClosed = true;
|
|
7326
|
+
this.events.emit("unsubscribe", void 0);
|
|
7327
|
+
this.events.clear();
|
|
7328
|
+
}
|
|
7313
7329
|
/**
|
|
7314
7330
|
* Internal method to handle incoming events from the WebSocket channel.
|
|
7315
7331
|
* If a handler is attached, it's invoked immediately. Otherwise, the event is buffered.
|
|
@@ -7356,14 +7372,24 @@ var Subscription = class {
|
|
|
7356
7372
|
if (this._isClosed) {
|
|
7357
7373
|
return true;
|
|
7358
7374
|
}
|
|
7359
|
-
|
|
7360
|
-
|
|
7361
|
-
this._isClosed = true;
|
|
7362
|
-
this.channel.removeSubscription(this.id);
|
|
7363
|
-
this.events.emit("unsubscribe", void 0);
|
|
7364
|
-
this.events.clear();
|
|
7375
|
+
if (this.pendingUnsubscribe) {
|
|
7376
|
+
return this.pendingUnsubscribe;
|
|
7365
7377
|
}
|
|
7366
|
-
|
|
7378
|
+
this.pendingUnsubscribe = (async () => {
|
|
7379
|
+
try {
|
|
7380
|
+
const success = await this.channel.unsubscribe(this.id);
|
|
7381
|
+
if (success) {
|
|
7382
|
+
this._isClosed = true;
|
|
7383
|
+
this.channel.removeSubscription(this.id);
|
|
7384
|
+
this.events.emit("unsubscribe", void 0);
|
|
7385
|
+
this.events.clear();
|
|
7386
|
+
}
|
|
7387
|
+
return success;
|
|
7388
|
+
} finally {
|
|
7389
|
+
this.pendingUnsubscribe = null;
|
|
7390
|
+
}
|
|
7391
|
+
})();
|
|
7392
|
+
return this.pendingUnsubscribe;
|
|
7367
7393
|
}
|
|
7368
7394
|
};
|
|
7369
7395
|
|
|
@@ -7396,6 +7422,15 @@ var WebSocketChannel = class {
|
|
|
7396
7422
|
requestQueue = [];
|
|
7397
7423
|
/** Abort handles for the requests currently on the wire, one per pending `sendReceive`. */
|
|
7398
7424
|
inFlight = /* @__PURE__ */ new Set();
|
|
7425
|
+
/**
|
|
7426
|
+
* Callers blocked in `waitForUnsubscription`, keyed by subscription id.
|
|
7427
|
+
*
|
|
7428
|
+
* Held here rather than as `unsubscribe` event listeners because that event only ever
|
|
7429
|
+
* announces success: a waiter attached to it cannot learn that the node refused the
|
|
7430
|
+
* unsubscribe or that the connection went away, and would wait forever with no timeout of
|
|
7431
|
+
* its own to fall back on.
|
|
7432
|
+
*/
|
|
7433
|
+
unsubscribeWaiters = /* @__PURE__ */ new Map();
|
|
7399
7434
|
events = new EventEmitter();
|
|
7400
7435
|
openListener = (ev) => {
|
|
7401
7436
|
this.scheduleReconnectAttemptsReset();
|
|
@@ -7592,6 +7627,7 @@ var WebSocketChannel = class {
|
|
|
7592
7627
|
this.isReconnecting = false;
|
|
7593
7628
|
this._rejectRequestQueue("the connection was closed by the user");
|
|
7594
7629
|
this._rejectInFlight("the connection was closed by the user");
|
|
7630
|
+
this._rejectUnsubscribeWaiters("the connection was closed by the user");
|
|
7595
7631
|
this.websocket.close(code, reason);
|
|
7596
7632
|
}
|
|
7597
7633
|
/**
|
|
@@ -7616,14 +7652,48 @@ var WebSocketChannel = class {
|
|
|
7616
7652
|
* @returns {Promise<boolean>} A Promise that resolves with `true` if the unsubscription was successful.
|
|
7617
7653
|
*/
|
|
7618
7654
|
async unsubscribe(subscriptionId) {
|
|
7619
|
-
|
|
7620
|
-
|
|
7621
|
-
|
|
7655
|
+
let status;
|
|
7656
|
+
try {
|
|
7657
|
+
status = await this.sendReceive("starknet_unsubscribe", {
|
|
7658
|
+
subscription_id: subscriptionId
|
|
7659
|
+
});
|
|
7660
|
+
} catch (error) {
|
|
7661
|
+
this._settleUnsubscribeWaiters(subscriptionId, error);
|
|
7662
|
+
throw error;
|
|
7663
|
+
}
|
|
7622
7664
|
if (status) {
|
|
7623
7665
|
this.events.emit("unsubscribe", subscriptionId);
|
|
7666
|
+
this._settleUnsubscribeWaiters(subscriptionId);
|
|
7667
|
+
} else {
|
|
7668
|
+
this._settleUnsubscribeWaiters(
|
|
7669
|
+
subscriptionId,
|
|
7670
|
+
new Error(`Node refused to unsubscribe subscription ${subscriptionId}`)
|
|
7671
|
+
);
|
|
7624
7672
|
}
|
|
7625
7673
|
return status;
|
|
7626
7674
|
}
|
|
7675
|
+
/** Settles every caller waiting on one subscription id: resolved, or rejected with `error`. */
|
|
7676
|
+
_settleUnsubscribeWaiters(subscriptionId, error) {
|
|
7677
|
+
const waiters = this.unsubscribeWaiters.get(subscriptionId);
|
|
7678
|
+
if (!waiters) return;
|
|
7679
|
+
this.unsubscribeWaiters.delete(subscriptionId);
|
|
7680
|
+
waiters.forEach((waiter) => error ? waiter.reject(error) : waiter.resolve());
|
|
7681
|
+
}
|
|
7682
|
+
/**
|
|
7683
|
+
* Rejects every caller still waiting on any subscription.
|
|
7684
|
+
*
|
|
7685
|
+
* Once the connection is gone, no unsubscribe can be observed on it: a reconnection restores
|
|
7686
|
+
* each subscription under a fresh id, so the id being waited on will never be announced.
|
|
7687
|
+
*/
|
|
7688
|
+
_rejectUnsubscribeWaiters(reason) {
|
|
7689
|
+
if (this.unsubscribeWaiters.size === 0) return;
|
|
7690
|
+
Array.from(this.unsubscribeWaiters.keys()).forEach(
|
|
7691
|
+
(id) => this._settleUnsubscribeWaiters(
|
|
7692
|
+
id,
|
|
7693
|
+
new WebSocketNotConnectedError(`Subscription ${id} was never unsubscribed: ${reason}`)
|
|
7694
|
+
)
|
|
7695
|
+
);
|
|
7696
|
+
}
|
|
7627
7697
|
/**
|
|
7628
7698
|
* Returns a Promise that resolves when a specific subscription is successfully unsubscribed.
|
|
7629
7699
|
* @param {SUBSCRIPTION_ID} targetId - The ID of the subscription to wait for.
|
|
@@ -7635,14 +7705,10 @@ var WebSocketChannel = class {
|
|
|
7635
7705
|
* ```
|
|
7636
7706
|
*/
|
|
7637
7707
|
waitForUnsubscription(targetId) {
|
|
7638
|
-
return new Promise((resolve) => {
|
|
7639
|
-
const
|
|
7640
|
-
|
|
7641
|
-
|
|
7642
|
-
resolve();
|
|
7643
|
-
}
|
|
7644
|
-
};
|
|
7645
|
-
this.events.on("unsubscribe", listener);
|
|
7708
|
+
return new Promise((resolve, reject) => {
|
|
7709
|
+
const waiters = this.unsubscribeWaiters.get(targetId) ?? /* @__PURE__ */ new Set();
|
|
7710
|
+
waiters.add({ resolve, reject });
|
|
7711
|
+
this.unsubscribeWaiters.set(targetId, waiters);
|
|
7646
7712
|
});
|
|
7647
7713
|
}
|
|
7648
7714
|
/**
|
|
@@ -7709,6 +7775,7 @@ var WebSocketChannel = class {
|
|
|
7709
7775
|
logger.info(`Subscription ${sub.method} restored with new ID: ${newSubId}`);
|
|
7710
7776
|
} catch (error) {
|
|
7711
7777
|
logger.error(`Failed to restore subscription ${sub.method}:`, error);
|
|
7778
|
+
sub._markClosed();
|
|
7712
7779
|
}
|
|
7713
7780
|
});
|
|
7714
7781
|
await Promise.all(restorePromises);
|
|
@@ -7778,6 +7845,7 @@ var WebSocketChannel = class {
|
|
|
7778
7845
|
this.websocket.removeEventListener("message", this.messageListener);
|
|
7779
7846
|
this.websocket.removeEventListener("error", this.errorListener);
|
|
7780
7847
|
this._rejectInFlight("the connection was closed");
|
|
7848
|
+
this._rejectUnsubscribeWaiters("the connection was closed");
|
|
7781
7849
|
this.events.emit("close", ev);
|
|
7782
7850
|
if (!this.userInitiatedClose) {
|
|
7783
7851
|
this._startReconnect();
|
|
@@ -7799,9 +7867,16 @@ var WebSocketChannel = class {
|
|
|
7799
7867
|
if (subscription) {
|
|
7800
7868
|
subscription._handleEvent(result);
|
|
7801
7869
|
} else {
|
|
7802
|
-
|
|
7803
|
-
|
|
7804
|
-
|
|
7870
|
+
queueMicrotask(() => {
|
|
7871
|
+
const registered = this.activeSubscriptions.get(subscription_id);
|
|
7872
|
+
if (registered) {
|
|
7873
|
+
registered._handleEvent(result);
|
|
7874
|
+
} else {
|
|
7875
|
+
logger.warn(
|
|
7876
|
+
`WebSocketChannel: Received event for untracked subscription ID: ${subscription_id}.`
|
|
7877
|
+
);
|
|
7878
|
+
}
|
|
7879
|
+
});
|
|
7805
7880
|
}
|
|
7806
7881
|
}
|
|
7807
7882
|
logger.debug("onMessageProxy:", event.data);
|
|
@@ -12852,7 +12927,7 @@ function fromWalletApiCall(call) {
|
|
|
12852
12927
|
}
|
|
12853
12928
|
function toWalletApiActions(actions) {
|
|
12854
12929
|
return actions.map(
|
|
12855
|
-
(action) => action.type === "
|
|
12930
|
+
(action) => action.type === "shadow_account_invoke" ? { ...action, calls: action.calls.map(toWalletApiCall) } : action
|
|
12856
12931
|
);
|
|
12857
12932
|
}
|
|
12858
12933
|
|
|
@@ -12871,7 +12946,7 @@ __export(connectV6_exports, {
|
|
|
12871
12946
|
strk20Balances: () => strk20Balances,
|
|
12872
12947
|
strk20InvokeTransaction: () => strk20InvokeTransaction,
|
|
12873
12948
|
strk20PrepareInvoke: () => strk20PrepareInvoke,
|
|
12874
|
-
|
|
12949
|
+
strk20ShadowAccountCommitment: () => strk20ShadowAccountCommitment,
|
|
12875
12950
|
subscribeWalletEvent: () => subscribeWalletEvent2,
|
|
12876
12951
|
supportedSpecs: () => supportedSpecs3,
|
|
12877
12952
|
supportedWalletApi: () => supportedWalletApi3,
|
|
@@ -12959,9 +13034,9 @@ function strk20InvokeTransaction(walletWSF, actions) {
|
|
|
12959
13034
|
params: { actions }
|
|
12960
13035
|
});
|
|
12961
13036
|
}
|
|
12962
|
-
function
|
|
13037
|
+
function strk20ShadowAccountCommitment(walletWSF, dapp_name, nonce) {
|
|
12963
13038
|
return walletWSF.features["starknet:walletApi"].request({
|
|
12964
|
-
type: "
|
|
13039
|
+
type: "wallet_strk20ShadowAccountCommitment",
|
|
12965
13040
|
params: { dapp_name, nonce }
|
|
12966
13041
|
});
|
|
12967
13042
|
}
|
|
@@ -13053,25 +13128,25 @@ var WalletAccountV6 = class _WalletAccountV6 extends WalletAccountV5 {
|
|
|
13053
13128
|
return strk20InvokeTransaction(this.v6Provider, toWalletApiActions(actions));
|
|
13054
13129
|
}
|
|
13055
13130
|
/**
|
|
13056
|
-
* Compute the commitment of a DAPP STRK20
|
|
13131
|
+
* Compute the commitment of a DAPP STRK20 shadow account. The commitment is computed
|
|
13057
13132
|
* locally by the wallet from the user private state ; no transaction is sent.
|
|
13058
13133
|
*
|
|
13059
|
-
* When `nonce` is given, the full commitment of this single
|
|
13134
|
+
* When `nonce` is given, the full commitment of this single shadow account is returned.
|
|
13060
13135
|
* When `nonce` is omitted, the partial (nonce independent) commitment is returned
|
|
13061
|
-
* instead : it is shared by every
|
|
13062
|
-
* be published once to let a DAPP recognize all the
|
|
13063
|
-
* learning any individual nonce.
|
|
13064
|
-
* @param {STRK20_DAPP_NAME} dappName - The DAPP that scopes the
|
|
13065
|
-
* @param {FELT} [nonce] - The
|
|
13066
|
-
* @returns {Promise<FELT>} The
|
|
13136
|
+
* instead : it is shared by every shadow account the user derives for this DAPP, so it
|
|
13137
|
+
* can be published once to let a DAPP recognize all the shadow accounts of a user
|
|
13138
|
+
* without learning any individual nonce.
|
|
13139
|
+
* @param {STRK20_DAPP_NAME} dappName - The DAPP that scopes the shadow account(s).
|
|
13140
|
+
* @param {FELT} [nonce] - The shadow account nonce ; each nonce selects a distinct shadow account for this user + DAPP. Omit it to get the partial commitment.
|
|
13141
|
+
* @returns {Promise<FELT>} The shadow account commitment.
|
|
13067
13142
|
* @example
|
|
13068
13143
|
* ```typescript
|
|
13069
|
-
* const commitment = await myWalletAccount.
|
|
13144
|
+
* const commitment = await myWalletAccount.strk20ShadowAccountCommitment('myDapp', '0x0');
|
|
13070
13145
|
* // commitment = '0x5f2e...'
|
|
13071
13146
|
* ```
|
|
13072
13147
|
*/
|
|
13073
|
-
|
|
13074
|
-
return
|
|
13148
|
+
strk20ShadowAccountCommitment(dappName, nonce) {
|
|
13149
|
+
return strk20ShadowAccountCommitment(this.v6Provider, dappName, nonce);
|
|
13075
13150
|
}
|
|
13076
13151
|
static async connect(provider, walletProvider, cairoVersion, paymaster, silentMode = false) {
|
|
13077
13152
|
const { accounts } = await standardConnect2(walletProvider, silentMode);
|