@bootnodedev/canton-connect 0.4.0 → 0.5.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 +4 -4
- package/dist/{CantonConnectProvider-CJ1yWGXz.js → CantonConnectProvider-M9GvvKOx.js} +33 -62
- package/dist/index.d.ts +31 -31
- package/dist/index.js +46 -45
- package/dist/testing/index.d.ts +7 -7
- package/dist/testing/index.js +11 -12
- package/dist/{types-CmnMRMoG.d.ts → types-BgMSHglV.d.ts} +50 -47
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -61,7 +61,7 @@ be present whether or not you set `walletConnectProjectId`. Only the session is
|
|
|
61
61
|
import {
|
|
62
62
|
CantonConnectProvider,
|
|
63
63
|
useConnect,
|
|
64
|
-
|
|
64
|
+
useAccount,
|
|
65
65
|
useWalletStatus,
|
|
66
66
|
useSignMessage,
|
|
67
67
|
useExecute,
|
|
@@ -78,7 +78,7 @@ function App() {
|
|
|
78
78
|
|
|
79
79
|
function Dapp() {
|
|
80
80
|
const { connect, isPending, isConnected, error } = useConnect()
|
|
81
|
-
const {
|
|
81
|
+
const { account } = useAccount()
|
|
82
82
|
const { isLocked } = useWalletStatus()
|
|
83
83
|
const { signMessage } = useSignMessage()
|
|
84
84
|
const { execute } = useExecute()
|
|
@@ -99,7 +99,7 @@ function Dapp() {
|
|
|
99
99
|
return <p>Wallet locked. Unlock it to continue.</p>
|
|
100
100
|
}
|
|
101
101
|
|
|
102
|
-
// ... your dApp:
|
|
102
|
+
// ... your dApp: account.partyId, signMessage(text), execute(params), ledgerApi(params)
|
|
103
103
|
}
|
|
104
104
|
```
|
|
105
105
|
|
|
@@ -114,7 +114,7 @@ reports it is not authenticated; that is `isLocked`, and it happens after a succ
|
|
|
114
114
|
reference gateway also refuses `signMessage` for a local party; `usePartyType().readPartyType()`
|
|
115
115
|
tells local from external when you ask. The SDK's status carries one `isConnected` flag, so a lock
|
|
116
116
|
and a wallet-side disconnect look the same
|
|
117
|
-
here. `useLedger().isReady` covers both, and `
|
|
117
|
+
here. `useLedger().isReady` covers both, and `useAccount().account` is `undefined` for the duration:
|
|
118
118
|
gate session content on the party, and use `isLocked` only to explain why it went away.
|
|
119
119
|
|
|
120
120
|
### Connecting through a Wallet Gateway
|
|
@@ -2,7 +2,6 @@ import { DappSDK, WalletConnectAdapter } from "@canton-network/dapp-sdk";
|
|
|
2
2
|
import { createContext, useCallback, useContext, useEffect, useMemo } from "react";
|
|
3
3
|
import { assign, enqueueActions, fromCallback, fromPromise, setup, waitFor } from "xstate";
|
|
4
4
|
import { useActorRef } from "@xstate/react";
|
|
5
|
-
import { WALLET_DISABLED_REASON } from "@canton-network/core-types";
|
|
6
5
|
import { jsx } from "react/jsx-runtime";
|
|
7
6
|
//#region src/CantonConnectProvider/adapters.ts
|
|
8
7
|
/** Builds the extra adapters for the SDK: WalletConnect when configured, plus any passed in. */
|
|
@@ -68,10 +67,18 @@ var ConnectCancelledError = class extends Error {
|
|
|
68
67
|
this.name = "ConnectCancelledError";
|
|
69
68
|
}
|
|
70
69
|
};
|
|
71
|
-
/**
|
|
72
|
-
const
|
|
70
|
+
/** Reads the text off a rejection: `message` as JSON-RPC sends it, `details` as the SDK does. */
|
|
71
|
+
const textOf = (cause) => {
|
|
72
|
+
if (typeof cause !== "object" || cause === null) return;
|
|
73
|
+
for (const key of ["message", "details"]) {
|
|
74
|
+
const value = cause[key];
|
|
75
|
+
if (typeof value === "string" && value !== "") return value;
|
|
76
|
+
}
|
|
77
|
+
};
|
|
73
78
|
/**
|
|
74
|
-
* Hands `cause` back as an `Error`, wrapping what a wallet answered with
|
|
79
|
+
* Hands `cause` back as an `Error`, wrapping what a wallet answered with. Nothing a wallet refuses
|
|
80
|
+
* arrives as an `Error`: the window transport rejects with the bare JSON-RPC object, and the SDK's
|
|
81
|
+
* own controller with a `{ status, error, details }` of its own, so both are read here.
|
|
75
82
|
*
|
|
76
83
|
* @example
|
|
77
84
|
* const error = toError(await sdk.signMessage(params).catch((cause: unknown) => cause))
|
|
@@ -79,7 +86,7 @@ const hasMessage = (cause) => typeof cause === "object" && cause !== null && "me
|
|
|
79
86
|
*/
|
|
80
87
|
const toError = (cause) => {
|
|
81
88
|
if (cause instanceof Error) return cause;
|
|
82
|
-
return new Error(
|
|
89
|
+
return new Error(textOf(cause) ?? String(cause), { cause });
|
|
83
90
|
};
|
|
84
91
|
/** Classifies what `sdk.connect()` threw, so the cancel path is decided once. */
|
|
85
92
|
const toConnectError = (cause) => {
|
|
@@ -102,41 +109,15 @@ const useConnectBridge = (actorRef) => {
|
|
|
102
109
|
}, [actorRef]);
|
|
103
110
|
};
|
|
104
111
|
//#endregion
|
|
105
|
-
//#region src/walletAccount.ts
|
|
106
|
-
/** Whether one raw account entry still has ledger rights to act as a party. */
|
|
107
|
-
const isUsable = (account) => {
|
|
108
|
-
if (account.status === "initialized" || account.status === "removed") return false;
|
|
109
|
-
if (account.disabled === true) return account.reason === WALLET_DISABLED_REASON.NO_SIGNING_PROVIDER_MATCHED;
|
|
110
|
-
return true;
|
|
111
|
-
};
|
|
112
|
-
/** Filters a raw account list down to the ones still usable as a party. */
|
|
113
|
-
const selectUsableAccounts = (accounts) => accounts.filter(isUsable);
|
|
114
|
-
/** Picks the account flagged `primary`, falling back to the first if none is. */
|
|
115
|
-
const selectPrimaryAccount = (accounts) => accounts.find((a) => a.primary) ?? accounts[0];
|
|
116
|
-
/** Maps one raw account entry to the public `Party` shape the hooks expose. */
|
|
117
|
-
const toParty = (account, fallbackNetworkId) => ({
|
|
118
|
-
partyId: account.partyId,
|
|
119
|
-
networkId: account.networkId ?? fallbackNetworkId,
|
|
120
|
-
namespace: account.namespace,
|
|
121
|
-
signingProviderId: account.signingProviderId,
|
|
122
|
-
...account.hint === void 0 ? {} : { name: account.hint },
|
|
123
|
-
...account.publicKey === void 0 ? {} : { publicKey: account.publicKey }
|
|
124
|
-
});
|
|
125
|
-
//#endregion
|
|
126
112
|
//#region src/machine/accountsActors.ts
|
|
127
|
-
/**
|
|
128
|
-
const
|
|
129
|
-
const primary = selectPrimaryAccount(selectUsableAccounts(accounts));
|
|
130
|
-
return { party: primary === void 0 ? void 0 : toParty(primary, networkId) };
|
|
131
|
-
};
|
|
132
|
-
/** Reads the wallet's account list once and resolves the primary usable party. */
|
|
133
|
-
const readAccounts = fromPromise(async ({ input: { sdk, networkId } }) => toWalletAccounts(await sdk.listAccounts(), networkId));
|
|
113
|
+
/** Reads the wallet's account list once and resolves the one it flags primary. */
|
|
114
|
+
const readPrimaryAccount = fromPromise(async ({ input: { sdk } }) => (await sdk.listAccounts()).find((account) => account.primary));
|
|
134
115
|
/** Forwards the wallet's own account-change pushes into the machine as `accounts.changed`. */
|
|
135
|
-
const accountsEvents = fromCallback(({ sendBack, input: { sdk
|
|
116
|
+
const accountsEvents = fromCallback(({ sendBack, input: { sdk } }) => {
|
|
136
117
|
const listener = (accounts) => {
|
|
137
118
|
sendBack({
|
|
138
119
|
type: "accounts.changed",
|
|
139
|
-
|
|
120
|
+
account: accounts.find((one) => one.primary)
|
|
140
121
|
});
|
|
141
122
|
};
|
|
142
123
|
sdk.onAccountsChanged(listener).catch(() => {});
|
|
@@ -147,17 +128,17 @@ const accountsEvents = fromCallback(({ sendBack, input: { sdk, networkId } }) =>
|
|
|
147
128
|
//#endregion
|
|
148
129
|
//#region src/machine/accountsMachine.ts
|
|
149
130
|
/**
|
|
150
|
-
* Reads the connected
|
|
131
|
+
* Reads the connected account once, then follows the wallet's own `accounts.changed` pushes.
|
|
151
132
|
* Invoked as `connectionMachine`'s `accounts` child while a session is authenticated.
|
|
152
133
|
*/
|
|
153
134
|
const accountsMachine = setup({
|
|
154
135
|
actors: {
|
|
155
|
-
|
|
136
|
+
readPrimaryAccount,
|
|
156
137
|
accountsEvents
|
|
157
138
|
},
|
|
158
139
|
actions: {
|
|
159
|
-
|
|
160
|
-
|
|
140
|
+
applyAccount: assign((_, params) => ({
|
|
141
|
+
account: params.account,
|
|
161
142
|
error: void 0
|
|
162
143
|
})),
|
|
163
144
|
assignError: assign((_, params) => ({ error: params.error }))
|
|
@@ -170,37 +151,31 @@ const accountsMachine = setup({
|
|
|
170
151
|
}).createMachine({
|
|
171
152
|
context: ({ input }) => ({
|
|
172
153
|
...input,
|
|
173
|
-
|
|
154
|
+
account: void 0,
|
|
174
155
|
error: void 0
|
|
175
156
|
}),
|
|
176
157
|
id: "accounts",
|
|
177
158
|
initial: "reading",
|
|
178
159
|
invoke: {
|
|
179
160
|
src: "accountsEvents",
|
|
180
|
-
input: ({ context: { sdk
|
|
181
|
-
sdk,
|
|
182
|
-
networkId
|
|
183
|
-
})
|
|
161
|
+
input: ({ context: { sdk } }) => ({ sdk })
|
|
184
162
|
},
|
|
185
163
|
on: { "accounts.changed": {
|
|
186
164
|
target: ".ready",
|
|
187
165
|
actions: {
|
|
188
|
-
type: "
|
|
189
|
-
params: ({ event: {
|
|
166
|
+
type: "applyAccount",
|
|
167
|
+
params: ({ event: { account } }) => ({ account })
|
|
190
168
|
}
|
|
191
169
|
} },
|
|
192
170
|
states: {
|
|
193
171
|
reading: { invoke: {
|
|
194
|
-
src: "
|
|
195
|
-
input: ({ context: { sdk
|
|
196
|
-
sdk,
|
|
197
|
-
networkId
|
|
198
|
-
}),
|
|
172
|
+
src: "readPrimaryAccount",
|
|
173
|
+
input: ({ context: { sdk } }) => ({ sdk }),
|
|
199
174
|
onDone: {
|
|
200
175
|
target: "ready",
|
|
201
176
|
actions: {
|
|
202
|
-
type: "
|
|
203
|
-
params: ({ event: { output } }) => ({
|
|
177
|
+
type: "applyAccount",
|
|
178
|
+
params: ({ event: { output } }) => ({ account: output })
|
|
204
179
|
}
|
|
205
180
|
},
|
|
206
181
|
onError: {
|
|
@@ -528,7 +503,7 @@ const connectionMachine = setup({
|
|
|
528
503
|
...input,
|
|
529
504
|
sdk: input.createSdk(),
|
|
530
505
|
lastConnectError: void 0,
|
|
531
|
-
|
|
506
|
+
account: void 0
|
|
532
507
|
}),
|
|
533
508
|
id: "connection",
|
|
534
509
|
initial: "idle",
|
|
@@ -568,19 +543,16 @@ const connectionMachine = setup({
|
|
|
568
543
|
states: {
|
|
569
544
|
authenticated: {
|
|
570
545
|
initial: "reading",
|
|
571
|
-
exit: assign({
|
|
546
|
+
exit: assign({ account: void 0 }),
|
|
572
547
|
invoke: {
|
|
573
548
|
src: "accounts",
|
|
574
549
|
id: "accounts",
|
|
575
|
-
input: ({ context }) => ({
|
|
576
|
-
sdk: context.sdk,
|
|
577
|
-
networkId: context.networkId
|
|
578
|
-
}),
|
|
550
|
+
input: ({ context }) => ({ sdk: context.sdk }),
|
|
579
551
|
onSnapshot: [{
|
|
580
552
|
guard: ({ event }) => event.snapshot.matches("ready"),
|
|
581
553
|
target: ".ready",
|
|
582
554
|
actions: assign(({ event }) => ({
|
|
583
|
-
|
|
555
|
+
account: event.snapshot.context.account,
|
|
584
556
|
lastConnectError: void 0
|
|
585
557
|
}))
|
|
586
558
|
}, {
|
|
@@ -746,8 +718,7 @@ const CantonConnectProvider = ({ config, children }) => {
|
|
|
746
718
|
const actorRef = useConnectionActor({
|
|
747
719
|
createSdk: () => new DappSDK({ walletPicker: config.walletPicker }),
|
|
748
720
|
initOptions: { additionalAdapters },
|
|
749
|
-
guardPicker: config.walletPicker === void 0
|
|
750
|
-
networkId
|
|
721
|
+
guardPicker: config.walletPicker === void 0
|
|
751
722
|
});
|
|
752
723
|
const resetConnectError = useCallback(() => actorRef.send({ type: "connectError.reset" }), [actorRef]);
|
|
753
724
|
const cancelConnect = useCallback(() => actorRef.send({ type: "connect.cancel" }), [actorRef]);
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as
|
|
1
|
+
import { a as ConnectionSubscription, c as TxStatusSnapshot, i as ConnectionStatus, l as ConnectionInput, n as CantonConnectConfig, o as DappSdkMethods, r as CantonConnectContextValue, s as PartyType, t as Account, u as InitOptions } from "./types-BgMSHglV.js";
|
|
2
2
|
import { LedgerApiParams, PrepareExecuteParams, ProviderAdapter } from "@canton-network/dapp-sdk";
|
|
3
3
|
import { JSX, ReactNode } from "react";
|
|
4
4
|
//#region src/CantonConnectProvider/index.d.ts
|
|
@@ -60,6 +60,32 @@ export declare class ConnectCancelledError extends Error {
|
|
|
60
60
|
constructor(cause?: unknown);
|
|
61
61
|
}
|
|
62
62
|
//#endregion
|
|
63
|
+
//#region src/hooks/useAccount.d.ts
|
|
64
|
+
/**
|
|
65
|
+
* Return shape of {@link useAccount}. `account` is the one the wallet flags primary, never
|
|
66
|
+
* substituted, and it changes under a live session.
|
|
67
|
+
*
|
|
68
|
+
* @category Hooks
|
|
69
|
+
*/
|
|
70
|
+
interface UseAccountResult {
|
|
71
|
+
account: Account | undefined;
|
|
72
|
+
status: ConnectionStatus;
|
|
73
|
+
isConnected: boolean;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* The connected account and status, as the wallet reports it. `account` is `undefined` until a
|
|
77
|
+
* connect succeeds, and again whenever a restored session is locked.
|
|
78
|
+
*
|
|
79
|
+
* @throws with no {@link CantonConnectProvider} above it.
|
|
80
|
+
*
|
|
81
|
+
* @example
|
|
82
|
+
* const { account, isConnected } = useAccount()
|
|
83
|
+
* isConnected && <span>{account?.hint}</span>
|
|
84
|
+
*
|
|
85
|
+
* @category Hooks
|
|
86
|
+
*/
|
|
87
|
+
export declare const useAccount: () => UseAccountResult;
|
|
88
|
+
//#endregion
|
|
63
89
|
//#region src/hooks/useConnect.d.ts
|
|
64
90
|
/**
|
|
65
91
|
* Return shape of {@link useConnect}.
|
|
@@ -80,7 +106,7 @@ interface UseConnectResult {
|
|
|
80
106
|
/**
|
|
81
107
|
* Connects the wallet and reports that transition. `connect` takes no argument: the picker chooses
|
|
82
108
|
* the wallet, so there is no mode to pass. Gate a pending face on `isPending` and
|
|
83
|
-
* session-dependent content on `
|
|
109
|
+
* session-dependent content on `useAccount().account`, not on `isConnected`.
|
|
84
110
|
*
|
|
85
111
|
* @throws with no {@link CantonConnectProvider} above it, as every hook here does.
|
|
86
112
|
*
|
|
@@ -137,7 +163,7 @@ interface UseExecuteResult {
|
|
|
137
163
|
}
|
|
138
164
|
/**
|
|
139
165
|
* Submits ledger commands and tracks the transaction in `lastTx`, fed by the SDK's `txChanged`
|
|
140
|
-
* event. `actAs` defaults to the party `
|
|
166
|
+
* event. `actAs` defaults to the party `useAccount` reports, so a submit acts as the party the UI
|
|
141
167
|
* shows rather than the wallet's own primary.
|
|
142
168
|
*
|
|
143
169
|
* @throws with no {@link CantonConnectProvider} above it, and from `execute` where nothing is
|
|
@@ -182,32 +208,6 @@ interface UseLedgerResult {
|
|
|
182
208
|
*/
|
|
183
209
|
export declare const useLedger: () => UseLedgerResult;
|
|
184
210
|
//#endregion
|
|
185
|
-
//#region src/hooks/useParty.d.ts
|
|
186
|
-
/**
|
|
187
|
-
* Return shape of {@link useParty}. `party` is the primary among the accounts that can act on the
|
|
188
|
-
* ledger, so it need not be the one the wallet flags primary, and it changes under a live session.
|
|
189
|
-
*
|
|
190
|
-
* @category Hooks
|
|
191
|
-
*/
|
|
192
|
-
interface UsePartyResult {
|
|
193
|
-
party: Party | undefined;
|
|
194
|
-
status: ConnectionStatus;
|
|
195
|
-
isConnected: boolean;
|
|
196
|
-
}
|
|
197
|
-
/**
|
|
198
|
-
* The connected account and status. `party` is `undefined` until a connect succeeds, and again
|
|
199
|
-
* whenever a restored session is locked.
|
|
200
|
-
*
|
|
201
|
-
* @throws with no {@link CantonConnectProvider} above it.
|
|
202
|
-
*
|
|
203
|
-
* @example
|
|
204
|
-
* const { party, isConnected } = useParty()
|
|
205
|
-
* isConnected && <span>{party?.partyId}</span>
|
|
206
|
-
*
|
|
207
|
-
* @category Hooks
|
|
208
|
-
*/
|
|
209
|
-
export declare const useParty: () => UsePartyResult;
|
|
210
|
-
//#endregion
|
|
211
211
|
//#region src/hooks/usePartyType.d.ts
|
|
212
212
|
/**
|
|
213
213
|
* Return shape of {@link usePartyType}. `readPartyType` throws when nothing is connected or no
|
|
@@ -309,7 +309,7 @@ interface MockAccount {
|
|
|
309
309
|
/**
|
|
310
310
|
* Wiring for {@link createMockAdapter}. `id` defaults to `'mock'`, which is the provider id
|
|
311
311
|
* `createAutoPicker('mock')` matches; `accounts` defaults to one generated account and treats the
|
|
312
|
-
* first entry as primary;
|
|
312
|
+
* first entry as primary; `networkId` defaults to `canton:local`.
|
|
313
313
|
*
|
|
314
314
|
* @example
|
|
315
315
|
* const options: CreateMockAdapterOptions = { id: 'mock', accounts: [{ partyId }] }
|
|
@@ -343,4 +343,4 @@ interface MockAdapter extends ProviderAdapter {
|
|
|
343
343
|
*/
|
|
344
344
|
export declare const createMockAdapter: (options?: CreateMockAdapterOptions) => MockAdapter;
|
|
345
345
|
//#endregion
|
|
346
|
-
export type { CantonConnectConfig, CantonConnectContextValue, CantonConnectProviderProps, ConnectionInput, ConnectionStatus, ConnectionSubscription, CreateMockAdapterOptions, InitOptions, LedgerApiParams, MockAccount, MockAdapter,
|
|
346
|
+
export type { Account, CantonConnectConfig, CantonConnectContextValue, CantonConnectProviderProps, ConnectionInput, ConnectionStatus, ConnectionSubscription, CreateMockAdapterOptions, DappSdkMethods, InitOptions, LedgerApiParams, MockAccount, MockAdapter, PartyType, PrepareExecuteParams, TxStatusSnapshot, UseAccountResult, UseConnectResult, UseDisconnectResult, UseExecuteResult, UseLedgerResult, UsePartyTypeResult, UseSignMessageResult, UseWalletStatusResult };
|
package/dist/index.js
CHANGED
|
@@ -1,11 +1,35 @@
|
|
|
1
|
-
import { a as toConnectionStatus, c as toError, n as CantonConnectProvider, o as ConnectCancelledError, r as useCantonConnectContext, s as toConnectError } from "./CantonConnectProvider-
|
|
1
|
+
import { a as toConnectionStatus, c as toError, n as CantonConnectProvider, o as ConnectCancelledError, r as useCantonConnectContext, s as toConnectError } from "./CantonConnectProvider-M9GvvKOx.js";
|
|
2
2
|
import { useCallback, useEffect, useMemo, useState } from "react";
|
|
3
3
|
import { useSelector } from "@xstate/react";
|
|
4
|
+
//#region src/hooks/useAccount.ts
|
|
5
|
+
/**
|
|
6
|
+
* The connected account and status, as the wallet reports it. `account` is `undefined` until a
|
|
7
|
+
* connect succeeds, and again whenever a restored session is locked.
|
|
8
|
+
*
|
|
9
|
+
* @throws with no {@link CantonConnectProvider} above it.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* const { account, isConnected } = useAccount()
|
|
13
|
+
* isConnected && <span>{account?.hint}</span>
|
|
14
|
+
*
|
|
15
|
+
* @category Hooks
|
|
16
|
+
*/
|
|
17
|
+
const useAccount = () => {
|
|
18
|
+
const { connection } = useCantonConnectContext();
|
|
19
|
+
const account = useSelector(connection, (snapshot) => snapshot.context.account);
|
|
20
|
+
const status = useSelector(connection, toConnectionStatus);
|
|
21
|
+
return {
|
|
22
|
+
account,
|
|
23
|
+
status,
|
|
24
|
+
isConnected: status === "connected"
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
//#endregion
|
|
4
28
|
//#region src/hooks/useConnect.ts
|
|
5
29
|
/**
|
|
6
30
|
* Connects the wallet and reports that transition. `connect` takes no argument: the picker chooses
|
|
7
31
|
* the wallet, so there is no mode to pass. Gate a pending face on `isPending` and
|
|
8
|
-
* session-dependent content on `
|
|
32
|
+
* session-dependent content on `useAccount().account`, not on `isConnected`.
|
|
9
33
|
*
|
|
10
34
|
* @throws with no {@link CantonConnectProvider} above it, as every hook here does.
|
|
11
35
|
*
|
|
@@ -92,9 +116,9 @@ const assertUsable = (status, isLocked) => {
|
|
|
92
116
|
if (status !== "connected") throw new Error("wallet is not connected - call useConnect().connect() first");
|
|
93
117
|
if (isLocked) throw new Error("wallet is locked - unlock it in the wallet");
|
|
94
118
|
};
|
|
95
|
-
/** Throws when the session reports no
|
|
119
|
+
/** Throws when the session reports no account, which a connected one can. */
|
|
96
120
|
function assertPartyId(partyId) {
|
|
97
|
-
if (partyId === void 0) throw new Error("wallet reports no
|
|
121
|
+
if (partyId === void 0) throw new Error("wallet reports no primary account - select or add one in the wallet");
|
|
98
122
|
}
|
|
99
123
|
/**
|
|
100
124
|
* Selects the session and wraps one SDK call with the connect, lock and party guards plus the
|
|
@@ -103,7 +127,7 @@ function assertPartyId(partyId) {
|
|
|
103
127
|
const useWalletCall = () => {
|
|
104
128
|
const { connection } = useCantonConnectContext();
|
|
105
129
|
const sdk = useSelector(connection, (snapshot) => snapshot.context.sdk);
|
|
106
|
-
const partyId = useSelector(connection, (snapshot) => snapshot.context.
|
|
130
|
+
const partyId = useSelector(connection, (snapshot) => snapshot.context.account?.partyId);
|
|
107
131
|
const status = useSelector(connection, toConnectionStatus);
|
|
108
132
|
const isLocked = useSelector(connection, (snapshot) => snapshot.hasTag("unauthenticated"));
|
|
109
133
|
const [state, setState] = useState(IDLE);
|
|
@@ -153,7 +177,7 @@ const withActAs = (params, partyId) => params.actAs === void 0 ? {
|
|
|
153
177
|
} : params;
|
|
154
178
|
/**
|
|
155
179
|
* Submits ledger commands and tracks the transaction in `lastTx`, fed by the SDK's `txChanged`
|
|
156
|
-
* event. `actAs` defaults to the party `
|
|
180
|
+
* event. `actAs` defaults to the party `useAccount` reports, so a submit acts as the party the UI
|
|
157
181
|
* shows rather than the wallet's own primary.
|
|
158
182
|
*
|
|
159
183
|
* @throws with no {@link CantonConnectProvider} above it, and from `execute` where nothing is
|
|
@@ -211,30 +235,6 @@ const useLedger = () => {
|
|
|
211
235
|
};
|
|
212
236
|
};
|
|
213
237
|
//#endregion
|
|
214
|
-
//#region src/hooks/useParty.ts
|
|
215
|
-
/**
|
|
216
|
-
* The connected account and status. `party` is `undefined` until a connect succeeds, and again
|
|
217
|
-
* whenever a restored session is locked.
|
|
218
|
-
*
|
|
219
|
-
* @throws with no {@link CantonConnectProvider} above it.
|
|
220
|
-
*
|
|
221
|
-
* @example
|
|
222
|
-
* const { party, isConnected } = useParty()
|
|
223
|
-
* isConnected && <span>{party?.partyId}</span>
|
|
224
|
-
*
|
|
225
|
-
* @category Hooks
|
|
226
|
-
*/
|
|
227
|
-
const useParty = () => {
|
|
228
|
-
const { connection } = useCantonConnectContext();
|
|
229
|
-
const party = useSelector(connection, (snapshot) => snapshot.context.party);
|
|
230
|
-
const status = useSelector(connection, toConnectionStatus);
|
|
231
|
-
return {
|
|
232
|
-
party,
|
|
233
|
-
status,
|
|
234
|
-
isConnected: status === "connected"
|
|
235
|
-
};
|
|
236
|
-
};
|
|
237
|
-
//#endregion
|
|
238
238
|
//#region src/hooks/usePartyType.ts
|
|
239
239
|
const namespaceOf = (id) => /::(.+)$/.exec(id)?.[1];
|
|
240
240
|
const readParticipantNamespace = async (sdk) => {
|
|
@@ -265,20 +265,20 @@ const readParticipantNamespace = async (sdk) => {
|
|
|
265
265
|
*/
|
|
266
266
|
const usePartyType = () => {
|
|
267
267
|
const { connection, sdk, status, isLocked } = useWalletCall();
|
|
268
|
-
const
|
|
268
|
+
const account = useSelector(connection, (snapshot) => snapshot.context.account);
|
|
269
269
|
return {
|
|
270
270
|
readPartyType: useCallback(async () => {
|
|
271
271
|
assertUsable(status, isLocked);
|
|
272
|
-
if (
|
|
272
|
+
if (account === void 0) throw new Error("wallet reports no primary account - select or add one in the wallet");
|
|
273
273
|
const participantNamespace = await readParticipantNamespace(sdk);
|
|
274
|
-
return
|
|
274
|
+
return account.namespace === participantNamespace ? "local" : "external";
|
|
275
275
|
}, [
|
|
276
|
+
account,
|
|
276
277
|
isLocked,
|
|
277
|
-
party,
|
|
278
278
|
sdk,
|
|
279
279
|
status
|
|
280
280
|
]),
|
|
281
|
-
isReady: status === "connected" && !isLocked &&
|
|
281
|
+
isReady: status === "connected" && !isLocked && account !== void 0
|
|
282
282
|
};
|
|
283
283
|
};
|
|
284
284
|
//#endregion
|
|
@@ -341,21 +341,22 @@ const useWalletStatus = () => {
|
|
|
341
341
|
const DEFAULT_PROVIDER_ID = "mock";
|
|
342
342
|
const DEFAULT_NAME = "Mock Wallet";
|
|
343
343
|
const DEFAULT_DESCRIPTION = "Mock wallet for dev and tests — no real signing, never a live wallet";
|
|
344
|
-
const
|
|
344
|
+
const MOCK_ACCOUNT_STATUS = "allocated";
|
|
345
345
|
const MOCK_SIGNING_PROVIDER_ID = "mock";
|
|
346
346
|
const MOCK_PUBLIC_KEY = "mock-public-key";
|
|
347
|
+
const MOCK_NETWORK_ID = "canton:local";
|
|
347
348
|
/** The single mock account `createMockAdapter` reports when the caller supplies none. */
|
|
348
349
|
const defaultAccounts = (providerId) => [{ partyId: `${providerId}::1220abcd` }];
|
|
349
|
-
/** Shapes one `MockAccount` into the `
|
|
350
|
-
const
|
|
350
|
+
/** Shapes one `MockAccount` into the `Account` the mock adapter's `listAccounts` returns. */
|
|
351
|
+
const toAccount = (account, primary, networkId) => ({
|
|
351
352
|
primary,
|
|
352
353
|
partyId: account.partyId,
|
|
353
|
-
status:
|
|
354
|
+
status: MOCK_ACCOUNT_STATUS,
|
|
354
355
|
hint: account.name ?? account.partyId,
|
|
355
356
|
publicKey: account.publicKey ?? MOCK_PUBLIC_KEY,
|
|
356
357
|
namespace: account.partyId.split("::")[1] ?? account.partyId,
|
|
357
|
-
|
|
358
|
-
|
|
358
|
+
networkId: networkId ?? MOCK_NETWORK_ID,
|
|
359
|
+
signingProviderId: MOCK_SIGNING_PROVIDER_ID
|
|
359
360
|
});
|
|
360
361
|
/**
|
|
361
362
|
* The adapter `createMockAdapter` returns: it announces itself like an installed wallet and
|
|
@@ -365,13 +366,13 @@ var MockProviderAdapter = class {
|
|
|
365
366
|
providerId;
|
|
366
367
|
name = DEFAULT_NAME;
|
|
367
368
|
type = "browser";
|
|
368
|
-
|
|
369
|
+
accounts;
|
|
369
370
|
connected = false;
|
|
370
371
|
listenerMap = {};
|
|
371
372
|
constructor(options) {
|
|
372
373
|
this.providerId = options.id ?? DEFAULT_PROVIDER_ID;
|
|
373
374
|
const accounts = options.accounts ?? defaultAccounts(this.providerId);
|
|
374
|
-
this.
|
|
375
|
+
this.accounts = accounts.map((account, index) => toAccount(account, index === 0, options.networkId));
|
|
375
376
|
}
|
|
376
377
|
getInfo() {
|
|
377
378
|
return {
|
|
@@ -410,7 +411,7 @@ var MockProviderAdapter = class {
|
|
|
410
411
|
isNetworkConnected: true
|
|
411
412
|
}
|
|
412
413
|
}),
|
|
413
|
-
listAccounts: () => this.
|
|
414
|
+
listAccounts: () => this.accounts
|
|
414
415
|
};
|
|
415
416
|
async request(args) {
|
|
416
417
|
const handler = this.handlers[args.method];
|
|
@@ -445,4 +446,4 @@ var MockProviderAdapter = class {
|
|
|
445
446
|
*/
|
|
446
447
|
const createMockAdapter = (options = {}) => new MockProviderAdapter(options);
|
|
447
448
|
//#endregion
|
|
448
|
-
export { CantonConnectProvider, ConnectCancelledError, createMockAdapter, useCantonConnectContext, useConnect, useDisconnect, useExecute, useLedger,
|
|
449
|
+
export { CantonConnectProvider, ConnectCancelledError, createMockAdapter, useAccount, useCantonConnectContext, useConnect, useDisconnect, useExecute, useLedger, usePartyType, useSignMessage, useWalletStatus };
|
package/dist/testing/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { i as ConnectionStatus, o as DappSdkMethods, t as Account } from "../types-BgMSHglV.js";
|
|
2
2
|
import { WalletPickerFn } from "@canton-network/dapp-sdk";
|
|
3
3
|
import { JSX, ReactNode } from "react";
|
|
4
4
|
//#region src/testing/autoPicker.d.ts
|
|
@@ -18,19 +18,19 @@ export declare const createAutoPicker: (pick?: string) => WalletPickerFn;
|
|
|
18
18
|
//#endregion
|
|
19
19
|
//#region src/testing/fakeSession.d.ts
|
|
20
20
|
/**
|
|
21
|
-
* Props for {@link FakeSessionProvider}. `status` starts the session mid-flight and `
|
|
21
|
+
* Props for {@link FakeSessionProvider}. `status` starts the session mid-flight and `account` is
|
|
22
22
|
* what a connect resolves to; `readingAccounts` reaches the pending face over a live session, and
|
|
23
23
|
* `sdk` drives a hook's own pending, error and `reset()`, never what a wallet returns.
|
|
24
24
|
*
|
|
25
25
|
* @category Components
|
|
26
26
|
*/
|
|
27
27
|
interface FakeSessionProviderProps {
|
|
28
|
+
account?: Account;
|
|
28
29
|
children: ReactNode;
|
|
29
30
|
connectError?: Error;
|
|
30
31
|
isLocked?: boolean;
|
|
31
|
-
party?: Party;
|
|
32
32
|
readingAccounts?: boolean;
|
|
33
|
-
sdk?: Partial<
|
|
33
|
+
sdk?: Partial<DappSdkMethods>;
|
|
34
34
|
status?: ConnectionStatus;
|
|
35
35
|
}
|
|
36
36
|
/**
|
|
@@ -43,19 +43,19 @@ interface FakeSessionProviderProps {
|
|
|
43
43
|
*
|
|
44
44
|
* @example
|
|
45
45
|
* render(
|
|
46
|
-
* <FakeSessionProvider status="connected"
|
|
46
|
+
* <FakeSessionProvider status="connected" account={account}>
|
|
47
47
|
* <ConnectButton />
|
|
48
48
|
* </FakeSessionProvider>,
|
|
49
49
|
* )
|
|
50
50
|
*
|
|
51
51
|
* @category Components
|
|
52
52
|
*/
|
|
53
|
-
export declare const FakeSessionProvider: ({ children, connectError, isLocked,
|
|
53
|
+
export declare const FakeSessionProvider: ({ account, children, connectError, isLocked, readingAccounts, sdk, status: initialStatus }: FakeSessionProviderProps) => JSX.Element;
|
|
54
54
|
//#endregion
|
|
55
55
|
//#region src/testing/fakeWallet.d.ts
|
|
56
56
|
/**
|
|
57
57
|
* One account the fake wallet reports from `listAccounts`. Mark exactly one `primary`: that is the
|
|
58
|
-
* entry
|
|
58
|
+
* entry the session reports.
|
|
59
59
|
*
|
|
60
60
|
* @category Utilities
|
|
61
61
|
*/
|
package/dist/testing/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { i as connectionMachine, t as CantonConnectContext } from "../CantonConnectProvider-
|
|
1
|
+
import { i as connectionMachine, t as CantonConnectContext } from "../CantonConnectProvider-M9GvvKOx.js";
|
|
2
2
|
import { useCallback, useEffect, useMemo, useState } from "react";
|
|
3
3
|
import { createActor } from "xstate";
|
|
4
|
-
import { CANTON_ANNOUNCE_PROVIDER_EVENT, CANTON_REQUEST_PROVIDER_EVENT, WalletEvent } from "@canton-network/core-types";
|
|
5
4
|
import { jsx } from "react/jsx-runtime";
|
|
5
|
+
import { CANTON_ANNOUNCE_PROVIDER_EVENT, CANTON_REQUEST_PROVIDER_EVENT, WalletEvent } from "@canton-network/core-types";
|
|
6
6
|
//#region src/testing/autoPicker.ts
|
|
7
7
|
/**
|
|
8
8
|
* A `walletPicker` that selects with no UI, for tests and headless dev flows: the entry whose
|
|
@@ -23,9 +23,9 @@ const createAutoPicker = (pick) => async (entries) => {
|
|
|
23
23
|
};
|
|
24
24
|
//#endregion
|
|
25
25
|
//#region src/testing/connectionInput.ts
|
|
26
|
-
/** A `
|
|
26
|
+
/** A `DappSdkMethods` method stand-in that returns a promise which never settles. */
|
|
27
27
|
const pending = () => new Promise(() => {});
|
|
28
|
-
/** Every `
|
|
28
|
+
/** Every `DappSdkMethods` method left hanging, so a test only stubs the ones its path reaches. */
|
|
29
29
|
const unstubbed = {
|
|
30
30
|
connect: pending,
|
|
31
31
|
disconnect: pending,
|
|
@@ -43,7 +43,7 @@ const unstubbed = {
|
|
|
43
43
|
status: pending
|
|
44
44
|
};
|
|
45
45
|
/**
|
|
46
|
-
* Machine input for a test actor, over a double satisfying the `
|
|
46
|
+
* Machine input for a test actor, over a double satisfying the `DappSdkMethods` the machine types.
|
|
47
47
|
* Whatever the double leaves out never settles, and every `createSdk()` hands back a fresh object,
|
|
48
48
|
* as `new DappSDK` does — so a retirement changes `context.sdk` here too.
|
|
49
49
|
*
|
|
@@ -57,7 +57,6 @@ const connectionInput = (sdk = {}, overrides = {}) => ({
|
|
|
57
57
|
}),
|
|
58
58
|
initOptions: {},
|
|
59
59
|
guardPicker: false,
|
|
60
|
-
networkId: "canton:local",
|
|
61
60
|
...overrides
|
|
62
61
|
});
|
|
63
62
|
//#endregion
|
|
@@ -77,7 +76,7 @@ const toStateValue = ({ isLocked, readingAccounts, status }) => {
|
|
|
77
76
|
return { session: { authenticated: readingAccounts ? "reading" : "ready" } };
|
|
78
77
|
};
|
|
79
78
|
/** Starts a real `connectionMachine` actor rehydrated at the given `SessionShape`. */
|
|
80
|
-
const startSession = (shape,
|
|
79
|
+
const startSession = (shape, account, connectError, sdk) => {
|
|
81
80
|
const input = connectionInput({}, { createSdk: () => sdk });
|
|
82
81
|
const snapshot = connectionMachine.resolveState({
|
|
83
82
|
value: toStateValue(shape),
|
|
@@ -85,7 +84,7 @@ const startSession = (shape, party, connectError, sdk) => {
|
|
|
85
84
|
...input,
|
|
86
85
|
sdk,
|
|
87
86
|
lastConnectError: connectError,
|
|
88
|
-
|
|
87
|
+
account: shape.status === "connected" ? account : void 0
|
|
89
88
|
}
|
|
90
89
|
});
|
|
91
90
|
return createActor(connectionMachine, {
|
|
@@ -103,23 +102,23 @@ const startSession = (shape, party, connectError, sdk) => {
|
|
|
103
102
|
*
|
|
104
103
|
* @example
|
|
105
104
|
* render(
|
|
106
|
-
* <FakeSessionProvider status="connected"
|
|
105
|
+
* <FakeSessionProvider status="connected" account={account}>
|
|
107
106
|
* <ConnectButton />
|
|
108
107
|
* </FakeSessionProvider>,
|
|
109
108
|
* )
|
|
110
109
|
*
|
|
111
110
|
* @category Components
|
|
112
111
|
*/
|
|
113
|
-
const FakeSessionProvider = ({ children, connectError, isLocked = false,
|
|
112
|
+
const FakeSessionProvider = ({ account, children, connectError, isLocked = false, readingAccounts = false, sdk = NO_SDK, status: initialStatus = "disconnected" }) => {
|
|
114
113
|
const [status, setStatus] = useState(initialStatus);
|
|
115
114
|
const connection = useMemo(() => startSession({
|
|
116
115
|
isLocked,
|
|
117
116
|
readingAccounts,
|
|
118
117
|
status
|
|
119
|
-
},
|
|
118
|
+
}, account, connectError, refusingSdk(sdk)), [
|
|
119
|
+
account,
|
|
120
120
|
connectError,
|
|
121
121
|
isLocked,
|
|
122
|
-
party,
|
|
123
122
|
readingAccounts,
|
|
124
123
|
sdk,
|
|
125
124
|
status
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { DappSDK, ProviderAdapter, StatusEvent, TxChangedEvent, WalletPickerFn } from "@canton-network/dapp-sdk";
|
|
1
|
+
import { DappSDK, ProviderAdapter, StatusEvent, TxChangedEvent, Wallet, WalletPickerFn } from "@canton-network/dapp-sdk";
|
|
2
2
|
import { ActorRefFrom } from "xstate";
|
|
3
3
|
//#region src/machine/connectionActors.d.ts
|
|
4
4
|
/**
|
|
@@ -36,17 +36,10 @@ type WalletEventsInput = {
|
|
|
36
36
|
sdk: Pick<DappSDK, 'onStatusChanged' | 'removeOnStatusChanged'>;
|
|
37
37
|
};
|
|
38
38
|
//#endregion
|
|
39
|
-
//#region src/machine/accountsMachine.d.ts
|
|
40
|
-
/** The result of an account read, initial or pushed: the party found, or none. */
|
|
41
|
-
type WalletAccounts = {
|
|
42
|
-
party: Party | undefined;
|
|
43
|
-
};
|
|
44
|
-
//#endregion
|
|
45
39
|
//#region src/machine/accountsActors.d.ts
|
|
46
|
-
/** Input shared by `
|
|
40
|
+
/** Input shared by `readPrimaryAccount` and `accountsEvents`: the sdk slice they call. */
|
|
47
41
|
type AccountsInput = {
|
|
48
42
|
sdk: Pick<DappSDK, 'listAccounts' | 'onAccountsChanged' | 'removeOnAccountsChanged'>;
|
|
49
|
-
networkId: string;
|
|
50
43
|
};
|
|
51
44
|
//#endregion
|
|
52
45
|
//#region src/machine/connectionMachine.d.ts
|
|
@@ -62,22 +55,21 @@ type WalletStatusUpdate = Pick<StatusEvent, 'connection'>;
|
|
|
62
55
|
* import { connectionMachine } from '#src/machine/connectionMachine'
|
|
63
56
|
*
|
|
64
57
|
* const createSdk = () => new DappSDK({})
|
|
65
|
-
* const input = { createSdk, initOptions: {}, guardPicker: true
|
|
58
|
+
* const input = { createSdk, initOptions: {}, guardPicker: true }
|
|
66
59
|
* createActor(connectionMachine, { input })
|
|
67
60
|
*
|
|
68
61
|
* @category Types
|
|
69
62
|
*/
|
|
70
63
|
type ConnectionInput = {
|
|
71
|
-
createSdk: () =>
|
|
64
|
+
createSdk: () => DappSdkMethods;
|
|
72
65
|
initOptions: InitOptions;
|
|
73
66
|
guardPicker: boolean;
|
|
74
|
-
networkId: string;
|
|
75
67
|
};
|
|
76
|
-
/** What the machine carries beyond its input: the sdk it drives, the last failure, the
|
|
68
|
+
/** What the machine carries beyond its input: the sdk it drives, the last failure, the account. */
|
|
77
69
|
type ConnectionContext = ConnectionInput & {
|
|
78
|
-
sdk:
|
|
70
|
+
sdk: DappSdkMethods;
|
|
79
71
|
lastConnectError: unknown;
|
|
80
|
-
|
|
72
|
+
account: Account | undefined;
|
|
81
73
|
};
|
|
82
74
|
/**
|
|
83
75
|
* The lifecycle itself: what a connect, a restore, a lock and a disconnect mean, and the tags the
|
|
@@ -101,25 +93,26 @@ declare const connectionMachine: import("xstate").StateMachine<ConnectionContext
|
|
|
101
93
|
status: WalletStatusUpdate;
|
|
102
94
|
}, {
|
|
103
95
|
[x: string]: import("xstate").ActorRefFromLogic<import("xstate").PromiseActorLogic<WalletStatusUpdate, ConnectInput, import("xstate").EventObject> | import("xstate").PromiseActorLogic<null, DisconnectInput, import("xstate").EventObject> | import("xstate").PromiseActorLogic<void, InitInput, import("xstate").EventObject> | import("xstate").PromiseActorLogic<WalletStatusUpdate, RestoreInput, import("xstate").EventObject> | import("xstate").CallbackActorLogic<import("xstate").EventObject, WalletEventsInput, import("xstate").EventObject>> | undefined;
|
|
104
|
-
accounts?: import("xstate").ActorRefFromLogic<import("xstate").StateMachine<AccountsInput &
|
|
96
|
+
accounts?: import("xstate").ActorRefFromLogic<import("xstate").StateMachine<AccountsInput & {
|
|
97
|
+
account: Account | undefined;
|
|
105
98
|
error: unknown;
|
|
106
99
|
}, {
|
|
107
100
|
type: "accounts.changed";
|
|
108
|
-
|
|
101
|
+
account: Account | undefined;
|
|
109
102
|
}, {
|
|
110
|
-
[x: string]: import("xstate").ActorRefFromLogic<import("xstate").PromiseActorLogic<
|
|
103
|
+
[x: string]: import("xstate").ActorRefFromLogic<import("xstate").PromiseActorLogic<import("@canton-network/dapp-sdk").Wallet | undefined, AccountsInput, import("xstate").EventObject> | import("xstate").CallbackActorLogic<import("xstate").EventObject, AccountsInput, import("xstate").EventObject>> | undefined;
|
|
111
104
|
}, {
|
|
112
|
-
src: "
|
|
113
|
-
logic: import("xstate").PromiseActorLogic<
|
|
105
|
+
src: "readPrimaryAccount";
|
|
106
|
+
logic: import("xstate").PromiseActorLogic<import("@canton-network/dapp-sdk").Wallet | undefined, AccountsInput, import("xstate").EventObject>;
|
|
114
107
|
id: string | undefined;
|
|
115
108
|
} | {
|
|
116
109
|
src: "accountsEvents";
|
|
117
110
|
logic: import("xstate").CallbackActorLogic<import("xstate").EventObject, AccountsInput, import("xstate").EventObject>;
|
|
118
111
|
id: string | undefined;
|
|
119
112
|
}, {
|
|
120
|
-
type: "
|
|
113
|
+
type: "applyAccount";
|
|
121
114
|
params: {
|
|
122
|
-
|
|
115
|
+
account: Account | undefined;
|
|
123
116
|
};
|
|
124
117
|
} | {
|
|
125
118
|
type: "assignError";
|
|
@@ -133,7 +126,7 @@ declare const connectionMachine: import("xstate").StateMachine<ConnectionContext
|
|
|
133
126
|
readonly ready: {};
|
|
134
127
|
readonly unavailable: {};
|
|
135
128
|
};
|
|
136
|
-
}>> | undefined;
|
|
129
|
+
}, import("xstate").MetaObject>> | undefined;
|
|
137
130
|
}, {
|
|
138
131
|
src: "init";
|
|
139
132
|
logic: import("xstate").PromiseActorLogic<void, InitInput, import("xstate").EventObject>;
|
|
@@ -156,25 +149,26 @@ declare const connectionMachine: import("xstate").StateMachine<ConnectionContext
|
|
|
156
149
|
id: string | undefined;
|
|
157
150
|
} | {
|
|
158
151
|
src: "accounts";
|
|
159
|
-
logic: import("xstate").StateMachine<AccountsInput &
|
|
152
|
+
logic: import("xstate").StateMachine<AccountsInput & {
|
|
153
|
+
account: Account | undefined;
|
|
160
154
|
error: unknown;
|
|
161
155
|
}, {
|
|
162
156
|
type: "accounts.changed";
|
|
163
|
-
|
|
157
|
+
account: Account | undefined;
|
|
164
158
|
}, {
|
|
165
|
-
[x: string]: import("xstate").ActorRefFromLogic<import("xstate").PromiseActorLogic<
|
|
159
|
+
[x: string]: import("xstate").ActorRefFromLogic<import("xstate").PromiseActorLogic<import("@canton-network/dapp-sdk").Wallet | undefined, AccountsInput, import("xstate").EventObject> | import("xstate").CallbackActorLogic<import("xstate").EventObject, AccountsInput, import("xstate").EventObject>> | undefined;
|
|
166
160
|
}, {
|
|
167
|
-
src: "
|
|
168
|
-
logic: import("xstate").PromiseActorLogic<
|
|
161
|
+
src: "readPrimaryAccount";
|
|
162
|
+
logic: import("xstate").PromiseActorLogic<import("@canton-network/dapp-sdk").Wallet | undefined, AccountsInput, import("xstate").EventObject>;
|
|
169
163
|
id: string | undefined;
|
|
170
164
|
} | {
|
|
171
165
|
src: "accountsEvents";
|
|
172
166
|
logic: import("xstate").CallbackActorLogic<import("xstate").EventObject, AccountsInput, import("xstate").EventObject>;
|
|
173
167
|
id: string | undefined;
|
|
174
168
|
}, {
|
|
175
|
-
type: "
|
|
169
|
+
type: "applyAccount";
|
|
176
170
|
params: {
|
|
177
|
-
|
|
171
|
+
account: Account | undefined;
|
|
178
172
|
};
|
|
179
173
|
} | {
|
|
180
174
|
type: "assignError";
|
|
@@ -188,7 +182,7 @@ declare const connectionMachine: import("xstate").StateMachine<ConnectionContext
|
|
|
188
182
|
readonly ready: {};
|
|
189
183
|
readonly unavailable: {};
|
|
190
184
|
};
|
|
191
|
-
}>;
|
|
185
|
+
}, import("xstate").MetaObject>;
|
|
192
186
|
id: "accounts";
|
|
193
187
|
}, {
|
|
194
188
|
type: "assignError";
|
|
@@ -270,7 +264,7 @@ declare const connectionMachine: import("xstate").StateMachine<ConnectionContext
|
|
|
270
264
|
readonly initializing: {};
|
|
271
265
|
readonly disconnecting: {};
|
|
272
266
|
};
|
|
273
|
-
}>;
|
|
267
|
+
}, import("xstate").MetaObject>;
|
|
274
268
|
/**
|
|
275
269
|
* The running connection machine. Consumers reach it narrowed to {@link ConnectionSubscription},
|
|
276
270
|
* so `send` stays inside this package.
|
|
@@ -286,14 +280,14 @@ type ConnectionActorRef = ActorRefFrom<typeof connectionMachine>;
|
|
|
286
280
|
*
|
|
287
281
|
* @category Types
|
|
288
282
|
*/
|
|
289
|
-
type
|
|
283
|
+
type DappSdkMethods = Pick<DappSDK, 'init' | 'connect' | 'disconnect' | 'status' | 'listAccounts' | 'onStatusChanged' | 'removeOnStatusChanged' | 'onAccountsChanged' | 'removeOnAccountsChanged' | 'onTxChanged' | 'removeOnTxChanged' | 'ledgerApi' | 'signMessage' | 'prepareExecuteAndWait'>;
|
|
290
284
|
/**
|
|
291
285
|
* `'idle'` is "not determined yet", not "disconnected": gate a connect button on `'disconnected'`,
|
|
292
286
|
* or a returning user is turned away before the boot restore runs. `'disconnecting'` is the session
|
|
293
287
|
* tearing down; keep connect disabled until it settles, so a new connect never overlaps it.
|
|
294
288
|
*
|
|
295
289
|
* @example
|
|
296
|
-
* const { status } =
|
|
290
|
+
* const { status } = useAccount()
|
|
297
291
|
* if (status === 'idle') return null
|
|
298
292
|
* return status === 'disconnected' ? <ConnectButton /> : <App />
|
|
299
293
|
*
|
|
@@ -307,21 +301,30 @@ type ConnectionStatus = 'idle' | 'connecting' | 'connected' | 'disconnecting' |
|
|
|
307
301
|
* @category Types
|
|
308
302
|
*/
|
|
309
303
|
type PartyType = 'local' | 'external';
|
|
304
|
+
type PinnedAccount = {
|
|
305
|
+
primary: boolean;
|
|
306
|
+
partyId: string;
|
|
307
|
+
status: 'initialized' | 'allocated' | 'removed';
|
|
308
|
+
hint: string;
|
|
309
|
+
publicKey: string;
|
|
310
|
+
namespace: string;
|
|
311
|
+
networkId: string;
|
|
312
|
+
signingProviderId: string;
|
|
313
|
+
externalTxId?: string;
|
|
314
|
+
topologyTransactions?: string;
|
|
315
|
+
disabled?: boolean;
|
|
316
|
+
reason?: string;
|
|
317
|
+
};
|
|
318
|
+
type Exact<A, B> = [A] extends [B] ? ([B] extends [A] ? true : false) : false;
|
|
319
|
+
type Assert<T extends true> = T;
|
|
320
|
+
type AccountPinned = Assert<Exact<Wallet, PinnedAccount>>;
|
|
310
321
|
/**
|
|
311
|
-
*
|
|
312
|
-
*
|
|
313
|
-
* `signingProviderId` come through as reported; CIP-0103 names no `signingProviderId` values.
|
|
322
|
+
* One account the connected wallet reports: a party plus its key, signing provider and network.
|
|
323
|
+
* `dapp-sdk` calls this type `Wallet`; CIP-0103's own text says account.
|
|
314
324
|
*
|
|
315
325
|
* @category Types
|
|
316
326
|
*/
|
|
317
|
-
|
|
318
|
-
partyId: string;
|
|
319
|
-
networkId: string;
|
|
320
|
-
namespace: string;
|
|
321
|
-
signingProviderId: string;
|
|
322
|
-
name?: string;
|
|
323
|
-
publicKey?: string;
|
|
324
|
-
}
|
|
327
|
+
type Account = AccountPinned extends true ? Wallet : never;
|
|
325
328
|
/**
|
|
326
329
|
* Wiring for `CantonConnectProvider`. From `appName` alone a local dev app works: `canton:local` as
|
|
327
330
|
* the network id and the WalletConnect chain id, `appName` as the description, the page origin as
|
|
@@ -376,7 +379,7 @@ interface TxStatusSnapshot {
|
|
|
376
379
|
* @example
|
|
377
380
|
* import type { ConnectionSubscription } from '#src/types'
|
|
378
381
|
*
|
|
379
|
-
* const
|
|
382
|
+
* const accountOf = (connection: ConnectionSubscription) => connection.getSnapshot().context.account
|
|
380
383
|
*
|
|
381
384
|
* @category Types
|
|
382
385
|
*/
|
|
@@ -397,4 +400,4 @@ interface CantonConnectContextValue {
|
|
|
397
400
|
resetConnectError: () => void;
|
|
398
401
|
}
|
|
399
402
|
//#endregion
|
|
400
|
-
export {
|
|
403
|
+
export { ConnectionSubscription as a, TxStatusSnapshot as c, ConnectionStatus as i, ConnectionInput as l, CantonConnectConfig as n, DappSdkMethods as o, CantonConnectContextValue as r, PartyType as s, Account as t, InitOptions as u };
|