Skip to content

Commit 50ff41e

Browse files
committed
fix(wallet-integration): address PR #85 feedback
- Replace signer.disconnect() with signer.closeChannel() (correct API per SDK docs) - Fix local dev section: remove conflation with @dfinity/oisy-wallet-signer - Add git clone step to working example deploy instructions - Add requestPermissions() note before getAccounts() - Add error code table to error handling section - Add Principal import to session persistence code block - Add forward-looking note about @dfinity/ledger-wallet-identity and @dfinity/icrc21-agent
1 parent 9c84435 commit 50ff41e

1 file changed

Lines changed: 43 additions & 13 deletions

File tree

docs/guides/defi/wallet-integration.md

Lines changed: 43 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,17 @@ const principal = accounts[0].owner;
7777

7878
`getAccounts()` triggers the wallet's `icrc27_accounts` flow. The popup opens, the user approves, and you receive their principal.
7979

80+
You can request permissions upfront before calling `getAccounts()` to batch all permission prompts into a single interaction:
81+
82+
```javascript
83+
// Request all needed permissions at once (optional but recommended)
84+
await signer.requestPermissions([{ method: 'icrc27_accounts' }]);
85+
86+
const accounts = await signer.getAccounts();
87+
```
88+
89+
If you skip this step, the signer handles permissions per-method — the user sees a permissions prompt the first time each method is called.
90+
8091
## Create a SignerAgent
8192

8293
`SignerAgent` wraps a `Signer` and acts as a drop-in replacement for `HttpAgent`. Any canister actor built with it routes calls through the wallet for approval.
@@ -133,19 +144,21 @@ const blockIndex = await signedLedger.transfer({
133144

134145
## Disconnect
135146

136-
Call `disconnect()` on the signer when the user logs out or closes the session:
147+
Call `closeChannel()` on the signer when the user logs out or closes the session:
137148

138149
```javascript
139-
await signer.disconnect();
150+
await signer.closeChannel();
140151
```
141152

142-
Disconnect closes the wallet popup and removes any cached session state.
153+
`closeChannel()` closes the open communication channel with the wallet popup.
143154

144155
## Session persistence
145156

146157
The signer session is tied to the browser tab. After a page reload, the user's principal is no longer available from the signer. To avoid opening the popup again immediately, store the principal in `sessionStorage` and restore it on mount — then re-establish the signer session lazily when the user initiates a transfer:
147158

148159
```javascript
160+
import { Principal } from '@icp-sdk/core/principal';
161+
149162
const SESSION_KEY = 'wallet-principal';
150163

151164
// On connect: store principal
@@ -172,17 +185,25 @@ try {
172185
await signer.getAccounts();
173186
} catch (err) {
174187
if (err instanceof SignerError) {
175-
// err.code: numeric error code from the ICRC-25 standard
176-
// err.message: human-readable description
177-
console.error('Signer error', err.code, err.message);
188+
switch (err.code) {
189+
case 3001: // ACTION_ABORTED — user closed the popup or rejected the prompt
190+
break;
191+
case 3000: // PERMISSION_NOT_GRANTED — permission was denied
192+
break;
193+
default:
194+
console.error('Signer error', err.code, err.message);
195+
}
178196
}
179197
}
180198
```
181199

182-
Common error scenarios:
183-
- User closes the wallet popup without approving
184-
- Wallet is not reachable at the configured URL
185-
- Call is rejected (user denies the consent message)
200+
Common `err.code` values from the ICRC-25 standard:
201+
202+
| Code | Meaning |
203+
|------|---------|
204+
| `3000` | Permission not granted |
205+
| `3001` | Action aborted — user closed the popup or rejected |
206+
| `4000` | Network error — IC call failed |
186207

187208
## Local development
188209

@@ -196,7 +217,7 @@ const signer = new Signer({
196217
const readAgent = await HttpAgent.create({ host: 'http://localhost:8000' });
197218
```
198219

199-
The `@dfinity/oisy-wallet-signer` repository includes a [pseudo wallet signer](https://github.com/dfinity/oisy-wallet-signer) you can run locally as a test signer. See its `demo/` directory for setup instructions.
220+
For a test signer target, you can use any ICRC-25-compliant wallet running locally that exposes a `/sign` endpoint — for example, a local instance of [OISY](https://github.com/dfinity/oisy-wallet) or a custom signer built with `@icp-sdk/signer`.
200221

201222
On mainnet, omit `host` from `HttpAgent.create()` — it defaults to `https://icp0.io`.
202223

@@ -211,13 +232,22 @@ The [oisy-signer-demo](https://github.com/dfinity/examples/tree/master/hosting/o
211232
To run locally:
212233

213234
```bash
214-
icp network start -d
235+
git clone https://github.com/dfinity/examples
215236
cd examples/hosting/oisy-signer-demo
237+
icp network start -d
216238
npm install
217-
cd frontend && npm install
218239
icp deploy
219240
```
220241

242+
## Ecosystem libraries
243+
244+
Two additional libraries are available for more advanced wallet integration scenarios:
245+
246+
- [`@dfinity/ledger-wallet-identity`](https://www.npmjs.com/package/@dfinity/ledger-wallet-identity) — hardware wallet identity support
247+
- [`@dfinity/icrc21-agent`](https://www.npmjs.com/package/@dfinity/icrc21-agent) — standalone ICRC-21 consent message agent
248+
249+
Both libraries are expected to move to the `@icp-sdk` namespace on npm and will likely be covered in the wallet-integration skill going forward. They are not documented in detail here.
250+
221251
## Next steps
222252

223253
- [Internet Identity integration](../authentication/internet-identity.md) — add authentication alongside wallet signing

0 commit comments

Comments
 (0)