@owney/sdk 0.7.21-beta.2 → 0.7.21-beta.4

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/dist/index.cjs CHANGED
@@ -2626,6 +2626,7 @@ var YieldseekerAuth = class {
2626
2626
  const inFlight = this.pending.get(key2);
2627
2627
  if (inFlight) return inFlight;
2628
2628
  const request = this.sign(state, chainId).then((token) => {
2629
+ if (this.pending.get(key2) !== request) throw new Error("Wallet sign-in session changed. Please try again.");
2629
2630
  this.tokens.set(key2, token);
2630
2631
  writeYieldseekerSession(scope.address, scope.chainId, token);
2631
2632
  return token;
@@ -2634,9 +2635,17 @@ var YieldseekerAuth = class {
2634
2635
  try {
2635
2636
  return await request;
2636
2637
  } finally {
2637
- this.pending.delete(key2);
2638
+ if (this.pending.get(key2) === request) this.pending.delete(key2);
2638
2639
  }
2639
2640
  }
2641
+ async refreshToken(state, chainId, rejectedToken) {
2642
+ const key2 = this.key(state, chainId);
2643
+ if (this.tokens.get(key2) === rejectedToken) {
2644
+ this.tokens.delete(key2);
2645
+ clearYieldseekerSession(state.walletAddress, chainId);
2646
+ }
2647
+ return this.getToken(state, chainId);
2648
+ }
2640
2649
  matchesOrigin(token) {
2641
2650
  try {
2642
2651
  const message = new import_siwe.SiweMessage(JSON.parse(atob(token)).message);
@@ -2784,7 +2793,7 @@ function providerError(body, fallback) {
2784
2793
  };
2785
2794
  }
2786
2795
  var YieldseekerApiClient = class {
2787
- constructor(owneyApiKey, baseUrl = YIELDSEEKER_API_BASE_URL, fetchFn = fetch) {
2796
+ constructor(owneyApiKey, baseUrl = YIELDSEEKER_API_BASE_URL, fetchFn = fetch.bind(globalThis)) {
2788
2797
  this.owneyApiKey = owneyApiKey;
2789
2798
  this.baseUrl = baseUrl;
2790
2799
  this.fetchFn = fetchFn;
@@ -3130,7 +3139,16 @@ function actionEntry(action) {
3130
3139
  rebalanceLog: []
3131
3140
  };
3132
3141
  }
3133
- function movementEntry(movement, wallet, agent, asset, ownerAddress, vaultAddresses) {
3142
+ function depositDestination(context, movement) {
3143
+ const to = movement.toAddress.toLowerCase();
3144
+ const option = context.positions.find(({ yieldOption }) => yieldOption.chainId === movement.chainId && yieldOption.assetAddress.toLowerCase() === context.agent.assetAddress.toLowerCase() && yieldOption.address.toLowerCase() === to)?.yieldOption;
3145
+ if (option) return { protocol: option.provider || "Vault", pool: option.name, tokenSymbol: context.asset };
3146
+ const receipt = context.historic?.assets.find((asset) => asset.chainId === movement.chainId && !asset.isSpam && asset.address.toLowerCase() === to && asset.address.toLowerCase() !== context.agent.assetAddress.toLowerCase());
3147
+ const minted = receipt && context.historic?.movements.some((candidate) => candidate.chainId === movement.chainId && candidate.transactionHash.toLowerCase() === movement.transactionHash.toLowerCase() && candidate.assetAddress.toLowerCase() === receipt.address.toLowerCase() && candidate.fromAddress.toLowerCase() === "0x0000000000000000000000000000000000000000" && candidate.toAddress.toLowerCase() === context.wallet.walletAddress.toLowerCase() && raw(candidate.assetAmount, "historic position") > 0n);
3148
+ if (receipt && minted) return { protocol: "Vault", pool: receipt.name || receipt.symbol, tokenSymbol: context.asset };
3149
+ return void 0;
3150
+ }
3151
+ function movementEntry(movement, wallet, agent, asset, ownerAddress, destination) {
3134
3152
  const from = movement.fromAddress.toLowerCase();
3135
3153
  const to = movement.toAddress.toLowerCase();
3136
3154
  const owner = ownerAddress.toLowerCase();
@@ -3144,13 +3162,17 @@ function movementEntry(movement, wallet, agent, asset, ownerAddress, vaultAddres
3144
3162
  action = "Top up";
3145
3163
  } else if (from === agentWallet && to === owner) {
3146
3164
  action = "Withdraw";
3147
- } else if (from === agentWallet && vaultAddresses.has(to)) {
3165
+ } else if (from === agentWallet && destination) {
3148
3166
  action = "Deposit";
3149
3167
  }
3150
3168
  if (!action) return void 0;
3151
3169
  return {
3152
3170
  agent: "yieldseeker",
3153
3171
  action,
3172
+ ...action === "Deposit" && destination ? { positions: [{
3173
+ ...destination,
3174
+ amount: decimal(movement.assetAmount, YIELDSEEKER_ASSET_METADATA[asset].decimals, "historic position")
3175
+ }] } : {},
3154
3176
  date: movement.blockDate,
3155
3177
  oldApy: null,
3156
3178
  newApy: null,
@@ -3171,34 +3193,52 @@ function movementEntry(movement, wallet, agent, asset, ownerAddress, vaultAddres
3171
3193
  }
3172
3194
  function mapYieldseekerHistory(contexts, options) {
3173
3195
  const entries = contexts.flatMap((context) => {
3174
- const vaultAddresses = new Set(
3175
- context.positions.map(
3176
- (position2) => position2.yieldOption.address.toLowerCase()
3177
- )
3178
- );
3196
+ const seenMovements = /* @__PURE__ */ new Set();
3197
+ const movements = (context.historic?.movements ?? []).filter((movement) => {
3198
+ const key2 = `${movement.chainId}:${movement.transactionHash.toLowerCase()}:${movement.logIndex}`;
3199
+ if (seenMovements.has(key2)) return false;
3200
+ seenMovements.add(key2);
3201
+ return true;
3202
+ });
3179
3203
  return [
3180
- ...(context.historic?.movements ?? []).map(
3204
+ ...movements.map(
3181
3205
  (movement) => movementEntry(
3182
3206
  movement,
3183
3207
  context.wallet,
3184
3208
  context.agent,
3185
3209
  context.asset,
3186
3210
  options.ownerAddress,
3187
- vaultAddresses
3211
+ depositDestination(context, movement)
3188
3212
  )
3189
3213
  ),
3190
3214
  ...(context.actions ?? []).map(actionEntry)
3191
3215
  ].filter((entry) => entry !== void 0);
3192
3216
  });
3193
- const filtered = entries.filter(
3194
- (entry) => (!options.fromDate || entry.date >= options.fromDate) && (!options.toDate || entry.date <= options.toDate)
3195
- ).filter((entry, index, all) => {
3196
- const transactionHash = entry.transactions[0]?.txHashes[0];
3197
- if (!transactionHash) return true;
3198
- return all.findIndex(
3199
- (candidate) => candidate.action === entry.action && candidate.transactions[0]?.txHashes[0] === transactionHash
3200
- ) === index;
3201
- }).sort((left, right) => right.date.localeCompare(left.date));
3217
+ const grouped = /* @__PURE__ */ new Map();
3218
+ const ungrouped = [];
3219
+ for (const entry of entries) {
3220
+ const tx = entry.transactions[0];
3221
+ const hash = tx?.txHashes[0];
3222
+ if (!hash) {
3223
+ ungrouped.push(entry);
3224
+ continue;
3225
+ }
3226
+ const key2 = `${entry.agent}:${entry.action}:${tx.chainId}:${hash.toLowerCase()}`;
3227
+ const previous = grouped.get(key2);
3228
+ if (!previous) {
3229
+ grouped.set(key2, entry);
3230
+ continue;
3231
+ }
3232
+ if (entry.action === "Deposit" && entry.positions?.length) {
3233
+ if (!previous.positions?.length) {
3234
+ grouped.set(key2, entry);
3235
+ continue;
3236
+ }
3237
+ previous.positions.push(...entry.positions);
3238
+ previous.transactions.push(...entry.transactions);
3239
+ }
3240
+ }
3241
+ const filtered = [...grouped.values(), ...ungrouped].filter((entry) => (!options.fromDate || entry.date >= options.fromDate) && (!options.toDate || entry.date <= options.toDate)).sort((left, right) => right.date.localeCompare(left.date));
3202
3242
  return {
3203
3243
  data: filtered.slice(0, options.limit),
3204
3244
  // v1 returns the whole action/movement collection and defines no cursor.
@@ -3845,8 +3885,7 @@ var YieldseekerAgent = class {
3845
3885
  if (!(error instanceof YieldseekerApiError)) throw error;
3846
3886
  if (error.providerCode === "NO_USER") throw error;
3847
3887
  if (!error.isAuthenticationError) throw error;
3848
- this.auth.clear(state, chainId);
3849
- signature = await this.auth.getToken(state, chainId);
3888
+ signature = await this.auth.refreshToken(state, chainId, signature);
3850
3889
  try {
3851
3890
  return await request(signature);
3852
3891
  } catch (retryError) {
@@ -4616,6 +4655,7 @@ var OwneySDK = class {
4616
4655
  * After calling this, `connect()` must be called again before using agent methods.
4617
4656
  */
4618
4657
  async disconnect() {
4658
+ this.state = null;
4619
4659
  for (const agent of this.agents.values()) {
4620
4660
  await agent.disconnect();
4621
4661
  }
@@ -4912,6 +4952,7 @@ var OwneySDK = class {
4912
4952
  async activateAgent(chainId, agentId, asset) {
4913
4953
  const state = this.requireState();
4914
4954
  await this.ensureAgentsInitialized();
4955
+ this.assertActivationSession(state);
4915
4956
  if (agentId !== void 0) {
4916
4957
  if (agentId.length === 0) {
4917
4958
  throw new OwneyError(
@@ -4968,6 +5009,11 @@ var OwneySDK = class {
4968
5009
  );
4969
5010
  await this.activateAgentsInTurn(enabledCompatible, state, chainId, asset);
4970
5011
  }
5012
+ assertActivationSession(state) {
5013
+ if (this.state !== state) {
5014
+ throw new OwneyError("NOT_CONNECTED", "Wallet connection changed. Please try again.");
5015
+ }
5016
+ }
4971
5017
  /**
4972
5018
  * Activate agents ONE AT A TIME, each followed by its org policy.
4973
5019
  *
@@ -4981,21 +5027,24 @@ var OwneySDK = class {
4981
5027
  * Serializing costs no real wall-clock: the user can only approve one prompt
4982
5028
  * at a time anyway.
4983
5029
  *
4984
- * Every agent is attempted even if an earlier one fails, so one declined
4985
- * signature can't deny the remaining agents their turn. Once all agents have
4986
- * had a chance, a partial failure identifies the agents that still need a
4987
- * retry; if none activated, the original provider error is preserved.
5030
+ * Stop at the first failure so a canceled sign-in does not open another
5031
+ * agent's wallet prompt. Report any earlier successes for diagnostics; the
5032
+ * app discards the session when the complete sign-in does not succeed.
4988
5033
  */
4989
5034
  async activateAgentsInTurn(agents, state, chainId, asset) {
4990
5035
  let firstError = null;
4991
5036
  const activatedAgentIds = [];
4992
5037
  const failedAgents = [];
4993
5038
  for (const agent of agents) {
5039
+ this.assertActivationSession(state);
4994
5040
  try {
4995
5041
  await agent.activateAgent(state, chainId, asset);
5042
+ this.assertActivationSession(state);
4996
5043
  await this.applyOrgPolicyTo(agent, state, chainId);
5044
+ this.assertActivationSession(state);
4997
5045
  activatedAgentIds.push(agent.id);
4998
5046
  } catch (error) {
5047
+ this.assertActivationSession(state);
4999
5048
  const message = error !== null && typeof error === "object" && "message" in error && typeof error.message === "string" ? error.message : typeof error === "string" ? error : "No activation error message was returned.";
5000
5049
  failedAgents.push({
5001
5050
  agentId: agent.id,
@@ -5008,6 +5057,7 @@ var OwneySDK = class {
5008
5057
  } else {
5009
5058
  console.error(`activateAgent(${agent.id}) failed:`, error);
5010
5059
  }
5060
+ break;
5011
5061
  }
5012
5062
  }
5013
5063
  if (firstError === null) return;
package/dist/index.d.cts CHANGED
@@ -587,6 +587,7 @@ declare class OwneySDK {
587
587
  * throws before activating any agent.
588
588
  */
589
589
  activateAgent(chainId: number, agentId?: AgentId[], asset?: OwneySupportedTokens): Promise<void>;
590
+ private assertActivationSession;
590
591
  /**
591
592
  * Activate agents ONE AT A TIME, each followed by its org policy.
592
593
  *
@@ -600,10 +601,9 @@ declare class OwneySDK {
600
601
  * Serializing costs no real wall-clock: the user can only approve one prompt
601
602
  * at a time anyway.
602
603
  *
603
- * Every agent is attempted even if an earlier one fails, so one declined
604
- * signature can't deny the remaining agents their turn. Once all agents have
605
- * had a chance, a partial failure identifies the agents that still need a
606
- * retry; if none activated, the original provider error is preserved.
604
+ * Stop at the first failure so a canceled sign-in does not open another
605
+ * agent's wallet prompt. Report any earlier successes for diagnostics; the
606
+ * app discards the session when the complete sign-in does not succeed.
607
607
  */
608
608
  private activateAgentsInTurn;
609
609
  /**
package/dist/index.d.ts CHANGED
@@ -587,6 +587,7 @@ declare class OwneySDK {
587
587
  * throws before activating any agent.
588
588
  */
589
589
  activateAgent(chainId: number, agentId?: AgentId[], asset?: OwneySupportedTokens): Promise<void>;
590
+ private assertActivationSession;
590
591
  /**
591
592
  * Activate agents ONE AT A TIME, each followed by its org policy.
592
593
  *
@@ -600,10 +601,9 @@ declare class OwneySDK {
600
601
  * Serializing costs no real wall-clock: the user can only approve one prompt
601
602
  * at a time anyway.
602
603
  *
603
- * Every agent is attempted even if an earlier one fails, so one declined
604
- * signature can't deny the remaining agents their turn. Once all agents have
605
- * had a chance, a partial failure identifies the agents that still need a
606
- * retry; if none activated, the original provider error is preserved.
604
+ * Stop at the first failure so a canceled sign-in does not open another
605
+ * agent's wallet prompt. Report any earlier successes for diagnostics; the
606
+ * app discards the session when the complete sign-in does not succeed.
607
607
  */
608
608
  private activateAgentsInTurn;
609
609
  /**
package/dist/index.js CHANGED
@@ -2605,6 +2605,7 @@ var YieldseekerAuth = class {
2605
2605
  const inFlight = this.pending.get(key2);
2606
2606
  if (inFlight) return inFlight;
2607
2607
  const request = this.sign(state, chainId).then((token) => {
2608
+ if (this.pending.get(key2) !== request) throw new Error("Wallet sign-in session changed. Please try again.");
2608
2609
  this.tokens.set(key2, token);
2609
2610
  writeYieldseekerSession(scope.address, scope.chainId, token);
2610
2611
  return token;
@@ -2613,9 +2614,17 @@ var YieldseekerAuth = class {
2613
2614
  try {
2614
2615
  return await request;
2615
2616
  } finally {
2616
- this.pending.delete(key2);
2617
+ if (this.pending.get(key2) === request) this.pending.delete(key2);
2617
2618
  }
2618
2619
  }
2620
+ async refreshToken(state, chainId, rejectedToken) {
2621
+ const key2 = this.key(state, chainId);
2622
+ if (this.tokens.get(key2) === rejectedToken) {
2623
+ this.tokens.delete(key2);
2624
+ clearYieldseekerSession(state.walletAddress, chainId);
2625
+ }
2626
+ return this.getToken(state, chainId);
2627
+ }
2619
2628
  matchesOrigin(token) {
2620
2629
  try {
2621
2630
  const message = new SiweMessage(JSON.parse(atob(token)).message);
@@ -2763,7 +2772,7 @@ function providerError(body, fallback) {
2763
2772
  };
2764
2773
  }
2765
2774
  var YieldseekerApiClient = class {
2766
- constructor(owneyApiKey, baseUrl = YIELDSEEKER_API_BASE_URL, fetchFn = fetch) {
2775
+ constructor(owneyApiKey, baseUrl = YIELDSEEKER_API_BASE_URL, fetchFn = fetch.bind(globalThis)) {
2767
2776
  this.owneyApiKey = owneyApiKey;
2768
2777
  this.baseUrl = baseUrl;
2769
2778
  this.fetchFn = fetchFn;
@@ -3109,7 +3118,16 @@ function actionEntry(action) {
3109
3118
  rebalanceLog: []
3110
3119
  };
3111
3120
  }
3112
- function movementEntry(movement, wallet, agent, asset, ownerAddress, vaultAddresses) {
3121
+ function depositDestination(context, movement) {
3122
+ const to = movement.toAddress.toLowerCase();
3123
+ const option = context.positions.find(({ yieldOption }) => yieldOption.chainId === movement.chainId && yieldOption.assetAddress.toLowerCase() === context.agent.assetAddress.toLowerCase() && yieldOption.address.toLowerCase() === to)?.yieldOption;
3124
+ if (option) return { protocol: option.provider || "Vault", pool: option.name, tokenSymbol: context.asset };
3125
+ const receipt = context.historic?.assets.find((asset) => asset.chainId === movement.chainId && !asset.isSpam && asset.address.toLowerCase() === to && asset.address.toLowerCase() !== context.agent.assetAddress.toLowerCase());
3126
+ const minted = receipt && context.historic?.movements.some((candidate) => candidate.chainId === movement.chainId && candidate.transactionHash.toLowerCase() === movement.transactionHash.toLowerCase() && candidate.assetAddress.toLowerCase() === receipt.address.toLowerCase() && candidate.fromAddress.toLowerCase() === "0x0000000000000000000000000000000000000000" && candidate.toAddress.toLowerCase() === context.wallet.walletAddress.toLowerCase() && raw(candidate.assetAmount, "historic position") > 0n);
3127
+ if (receipt && minted) return { protocol: "Vault", pool: receipt.name || receipt.symbol, tokenSymbol: context.asset };
3128
+ return void 0;
3129
+ }
3130
+ function movementEntry(movement, wallet, agent, asset, ownerAddress, destination) {
3113
3131
  const from = movement.fromAddress.toLowerCase();
3114
3132
  const to = movement.toAddress.toLowerCase();
3115
3133
  const owner = ownerAddress.toLowerCase();
@@ -3123,13 +3141,17 @@ function movementEntry(movement, wallet, agent, asset, ownerAddress, vaultAddres
3123
3141
  action = "Top up";
3124
3142
  } else if (from === agentWallet && to === owner) {
3125
3143
  action = "Withdraw";
3126
- } else if (from === agentWallet && vaultAddresses.has(to)) {
3144
+ } else if (from === agentWallet && destination) {
3127
3145
  action = "Deposit";
3128
3146
  }
3129
3147
  if (!action) return void 0;
3130
3148
  return {
3131
3149
  agent: "yieldseeker",
3132
3150
  action,
3151
+ ...action === "Deposit" && destination ? { positions: [{
3152
+ ...destination,
3153
+ amount: decimal(movement.assetAmount, YIELDSEEKER_ASSET_METADATA[asset].decimals, "historic position")
3154
+ }] } : {},
3133
3155
  date: movement.blockDate,
3134
3156
  oldApy: null,
3135
3157
  newApy: null,
@@ -3150,34 +3172,52 @@ function movementEntry(movement, wallet, agent, asset, ownerAddress, vaultAddres
3150
3172
  }
3151
3173
  function mapYieldseekerHistory(contexts, options) {
3152
3174
  const entries = contexts.flatMap((context) => {
3153
- const vaultAddresses = new Set(
3154
- context.positions.map(
3155
- (position2) => position2.yieldOption.address.toLowerCase()
3156
- )
3157
- );
3175
+ const seenMovements = /* @__PURE__ */ new Set();
3176
+ const movements = (context.historic?.movements ?? []).filter((movement) => {
3177
+ const key2 = `${movement.chainId}:${movement.transactionHash.toLowerCase()}:${movement.logIndex}`;
3178
+ if (seenMovements.has(key2)) return false;
3179
+ seenMovements.add(key2);
3180
+ return true;
3181
+ });
3158
3182
  return [
3159
- ...(context.historic?.movements ?? []).map(
3183
+ ...movements.map(
3160
3184
  (movement) => movementEntry(
3161
3185
  movement,
3162
3186
  context.wallet,
3163
3187
  context.agent,
3164
3188
  context.asset,
3165
3189
  options.ownerAddress,
3166
- vaultAddresses
3190
+ depositDestination(context, movement)
3167
3191
  )
3168
3192
  ),
3169
3193
  ...(context.actions ?? []).map(actionEntry)
3170
3194
  ].filter((entry) => entry !== void 0);
3171
3195
  });
3172
- const filtered = entries.filter(
3173
- (entry) => (!options.fromDate || entry.date >= options.fromDate) && (!options.toDate || entry.date <= options.toDate)
3174
- ).filter((entry, index, all) => {
3175
- const transactionHash = entry.transactions[0]?.txHashes[0];
3176
- if (!transactionHash) return true;
3177
- return all.findIndex(
3178
- (candidate) => candidate.action === entry.action && candidate.transactions[0]?.txHashes[0] === transactionHash
3179
- ) === index;
3180
- }).sort((left, right) => right.date.localeCompare(left.date));
3196
+ const grouped = /* @__PURE__ */ new Map();
3197
+ const ungrouped = [];
3198
+ for (const entry of entries) {
3199
+ const tx = entry.transactions[0];
3200
+ const hash = tx?.txHashes[0];
3201
+ if (!hash) {
3202
+ ungrouped.push(entry);
3203
+ continue;
3204
+ }
3205
+ const key2 = `${entry.agent}:${entry.action}:${tx.chainId}:${hash.toLowerCase()}`;
3206
+ const previous = grouped.get(key2);
3207
+ if (!previous) {
3208
+ grouped.set(key2, entry);
3209
+ continue;
3210
+ }
3211
+ if (entry.action === "Deposit" && entry.positions?.length) {
3212
+ if (!previous.positions?.length) {
3213
+ grouped.set(key2, entry);
3214
+ continue;
3215
+ }
3216
+ previous.positions.push(...entry.positions);
3217
+ previous.transactions.push(...entry.transactions);
3218
+ }
3219
+ }
3220
+ const filtered = [...grouped.values(), ...ungrouped].filter((entry) => (!options.fromDate || entry.date >= options.fromDate) && (!options.toDate || entry.date <= options.toDate)).sort((left, right) => right.date.localeCompare(left.date));
3181
3221
  return {
3182
3222
  data: filtered.slice(0, options.limit),
3183
3223
  // v1 returns the whole action/movement collection and defines no cursor.
@@ -3824,8 +3864,7 @@ var YieldseekerAgent = class {
3824
3864
  if (!(error instanceof YieldseekerApiError)) throw error;
3825
3865
  if (error.providerCode === "NO_USER") throw error;
3826
3866
  if (!error.isAuthenticationError) throw error;
3827
- this.auth.clear(state, chainId);
3828
- signature = await this.auth.getToken(state, chainId);
3867
+ signature = await this.auth.refreshToken(state, chainId, signature);
3829
3868
  try {
3830
3869
  return await request(signature);
3831
3870
  } catch (retryError) {
@@ -4599,6 +4638,7 @@ var OwneySDK = class {
4599
4638
  * After calling this, `connect()` must be called again before using agent methods.
4600
4639
  */
4601
4640
  async disconnect() {
4641
+ this.state = null;
4602
4642
  for (const agent of this.agents.values()) {
4603
4643
  await agent.disconnect();
4604
4644
  }
@@ -4895,6 +4935,7 @@ var OwneySDK = class {
4895
4935
  async activateAgent(chainId, agentId, asset) {
4896
4936
  const state = this.requireState();
4897
4937
  await this.ensureAgentsInitialized();
4938
+ this.assertActivationSession(state);
4898
4939
  if (agentId !== void 0) {
4899
4940
  if (agentId.length === 0) {
4900
4941
  throw new OwneyError(
@@ -4951,6 +4992,11 @@ var OwneySDK = class {
4951
4992
  );
4952
4993
  await this.activateAgentsInTurn(enabledCompatible, state, chainId, asset);
4953
4994
  }
4995
+ assertActivationSession(state) {
4996
+ if (this.state !== state) {
4997
+ throw new OwneyError("NOT_CONNECTED", "Wallet connection changed. Please try again.");
4998
+ }
4999
+ }
4954
5000
  /**
4955
5001
  * Activate agents ONE AT A TIME, each followed by its org policy.
4956
5002
  *
@@ -4964,21 +5010,24 @@ var OwneySDK = class {
4964
5010
  * Serializing costs no real wall-clock: the user can only approve one prompt
4965
5011
  * at a time anyway.
4966
5012
  *
4967
- * Every agent is attempted even if an earlier one fails, so one declined
4968
- * signature can't deny the remaining agents their turn. Once all agents have
4969
- * had a chance, a partial failure identifies the agents that still need a
4970
- * retry; if none activated, the original provider error is preserved.
5013
+ * Stop at the first failure so a canceled sign-in does not open another
5014
+ * agent's wallet prompt. Report any earlier successes for diagnostics; the
5015
+ * app discards the session when the complete sign-in does not succeed.
4971
5016
  */
4972
5017
  async activateAgentsInTurn(agents, state, chainId, asset) {
4973
5018
  let firstError = null;
4974
5019
  const activatedAgentIds = [];
4975
5020
  const failedAgents = [];
4976
5021
  for (const agent of agents) {
5022
+ this.assertActivationSession(state);
4977
5023
  try {
4978
5024
  await agent.activateAgent(state, chainId, asset);
5025
+ this.assertActivationSession(state);
4979
5026
  await this.applyOrgPolicyTo(agent, state, chainId);
5027
+ this.assertActivationSession(state);
4980
5028
  activatedAgentIds.push(agent.id);
4981
5029
  } catch (error) {
5030
+ this.assertActivationSession(state);
4982
5031
  const message = error !== null && typeof error === "object" && "message" in error && typeof error.message === "string" ? error.message : typeof error === "string" ? error : "No activation error message was returned.";
4983
5032
  failedAgents.push({
4984
5033
  agentId: agent.id,
@@ -4991,6 +5040,7 @@ var OwneySDK = class {
4991
5040
  } else {
4992
5041
  console.error(`activateAgent(${agent.id}) failed:`, error);
4993
5042
  }
5043
+ break;
4994
5044
  }
4995
5045
  }
4996
5046
  if (firstError === null) return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@owney/sdk",
3
- "version": "0.7.21-beta.2",
3
+ "version": "0.7.21-beta.4",
4
4
  "type": "module",
5
5
  "main": "dist/index.cjs",
6
6
  "module": "dist/index.js",