Skip to content

Commit c9ed02e

Browse files
tomiirCopilot
andauthored
feat: enable custom SIWXSigner (#5238)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
1 parent 3d36c15 commit c9ed02e

12 files changed

Lines changed: 114 additions & 21 deletions

File tree

.changeset/slow-symbols-own.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
'@reown/appkit-controllers': patch
3+
'@reown/appkit-scaffold-ui': patch
4+
'@reown/appkit': patch
5+
'@reown/appkit-siwx': patch
6+
---
7+
8+
Adds ability to configure custom SIWX signing behaviors by implementing a custom `SIWXSigner`
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
export * from '../src/features/reown-authentication/index.js'
1+
export * from '../src/features/siwx/reown-authentication/index.js'

packages/controllers/src/features/siwx/DefaultSigner.ts

Whitespace-only changes.

packages/controllers/src/features/reown-authentication/ReownAuthentication.ts renamed to packages/controllers/src/features/siwx/reown-authentication/ReownAuthentication.ts

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@ import {
88
SafeLocalStorageKeys
99
} from '@reown/appkit-common'
1010

11-
import { ApiController } from '../../controllers/ApiController.js'
12-
import { BlockchainApiController } from '../../controllers/BlockchainApiController.js'
13-
import { ChainController } from '../../controllers/ChainController.js'
14-
import { getActiveCaipNetwork } from '../../utils/ChainControllerUtil.js'
15-
import type { SIWXConfig, SIWXMessage, SIWXSession } from '../../utils/SIWXUtil.js'
11+
import { ApiController } from '../../../controllers/ApiController.js'
12+
import { BlockchainApiController } from '../../../controllers/BlockchainApiController.js'
13+
import { ChainController } from '../../../controllers/ChainController.js'
14+
import { getActiveCaipNetwork } from '../../../utils/ChainControllerUtil.js'
15+
import type { SIWXConfig, SIWXMessage, SIWXSession } from '../../../utils/SIWXUtil.js'
1616
import { ReownAuthenticationMessenger } from './ReownAuthenticationMessenger.js'
1717

1818
/**
@@ -23,7 +23,6 @@ export class ReownAuthentication implements SIWXConfig {
2323
private readonly localAuthStorageKey: keyof SafeLocalStorageItems
2424
private readonly localNonceStorageKey: keyof SafeLocalStorageItems
2525
private readonly messenger: ReownAuthenticationMessenger
26-
2726
private required: boolean
2827
private otpUuid: string | null = null
2928

packages/controllers/src/features/reown-authentication/ReownAuthenticationMessenger.ts renamed to packages/controllers/src/features/siwx/reown-authentication/ReownAuthenticationMessenger.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { type CaipNetworkId, NetworkUtil } from '@reown/appkit-common'
22

3-
import { ChainController } from '../../controllers/ChainController.js'
4-
import type { SIWXMessage } from '../../utils/SIWXUtil.js'
3+
import { ChainController } from '../../../controllers/ChainController.js'
4+
import type { SIWXMessage } from '../../../utils/SIWXUtil.js'
55

66
export class ReownAuthenticationMessenger {
77
public resources?: SIWXMessage['resources']

packages/controllers/src/features/reown-authentication/index.ts renamed to packages/controllers/src/features/siwx/reown-authentication/index.ts

File renamed without changes.

packages/controllers/src/features/siwx/types.ts

Whitespace-only changes.

packages/controllers/src/utils/SIWXUtil.ts

Lines changed: 35 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,6 @@ export const SIWXUtil = {
102102
const siwx = OptionsController.state.siwx
103103
const address = CoreHelperUtil.getPlainAddress(ChainController.getActiveCaipAddress())
104104
const network = getActiveCaipNetwork()
105-
const client = ConnectionController._getClient()
106105

107106
if (!siwx) {
108107
throw new Error('SIWX is not enabled')
@@ -116,25 +115,29 @@ export const SIWXUtil = {
116115
throw new Error('No ActiveCaipNetwork or client found')
117116
}
118117

119-
if (!client) {
120-
throw new Error('No ConnectionController client found')
121-
}
122-
123118
try {
124119
const siwxMessage = await siwx.createMessage({
125120
chainId: network.caipNetworkId,
126121
accountAddress: address
127122
})
128123

129124
const message = siwxMessage.toString()
130-
const connectorId = ConnectorController.getConnectorId(network.chainNamespace)
131125

132-
if (connectorId === CommonConstantsUtil.CONNECTOR_ID.AUTH) {
133-
RouterController.pushTransactionStack({})
126+
let signature = ''
127+
if (siwx.signMessage) {
128+
signature = await siwx.signMessage({
129+
message,
130+
chainId: network.caipNetworkId,
131+
accountAddress: address
132+
})
133+
} else {
134+
const connectorId = ConnectorController.getConnectorId(network.chainNamespace)
135+
if (connectorId === CommonConstantsUtil.CONNECTOR_ID.AUTH) {
136+
RouterController.pushTransactionStack({})
137+
}
138+
signature = (await ConnectionController.signMessage(message)) || ''
134139
}
135140

136-
const signature = await client.signMessage(message)
137-
138141
await siwx.addSession({
139142
data: siwxMessage,
140143
message,
@@ -523,6 +526,28 @@ export interface SIWXConfig {
523526
*/
524527
createMessage: (input: SIWXMessage.Input) => Promise<SIWXMessage>
525528

529+
/**
530+
* This method will be called to sign a message with the wallet using the signer handler.
531+
* This behavior can be overriden by passing in a `signer` parameter to the `SIWXConfig` constructor.
532+
* Constraints:
533+
* - This method MUST forward the message to the wallet for a signature request.
534+
* - If the signature process fails or is cancelled it MUST throw an error.
535+
*
536+
* @param message string
537+
* @param chainId CaipNetworkId
538+
* @param accountAddress string
539+
* @returns string
540+
*/
541+
signMessage?: ({
542+
message,
543+
chainId,
544+
accountAddress
545+
}: {
546+
message: string
547+
chainId: string
548+
accountAddress: string
549+
}) => Promise<string>
550+
526551
/**
527552
* This method will be called to store a new single session.
528553
*

packages/siwx/src/configs/DefaultSIWX.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { SIWXConfig } from '../core/SIWXConfig.js'
22
import { InformalMessenger } from '../messengers/index.js'
3+
import DefaultSigner from '../signers/DefaultSigner.js'
34
import { LocalStorage } from '../storages/index.js'
45
import { BIP122Verifier } from '../verifiers/BIP122Verifier.js'
56
import { EIP155Verifier, SolanaVerifier } from '../verifiers/index.js'
@@ -19,7 +20,9 @@ const DEFAULTS = {
1920

2021
getDefaultVerifiers: () => [new EIP155Verifier(), new SolanaVerifier(), new BIP122Verifier()],
2122

22-
getDefaultStorage: () => new LocalStorage({ key: '@appkit/siwx' })
23+
getDefaultStorage: () => new LocalStorage({ key: '@appkit/siwx' }),
24+
25+
getDefaultSigner: () => new DefaultSigner()
2326
}
2427

2528
/**
@@ -35,7 +38,8 @@ export class DefaultSIWX extends SIWXConfig {
3538
messenger: params.messenger || DEFAULTS.getDefaultMessenger(),
3639
verifiers: params.verifiers || DEFAULTS.getDefaultVerifiers(),
3740
storage: params.storage || DEFAULTS.getDefaultStorage(),
38-
required: params.required
41+
required: params.required,
42+
signer: params.signer || DEFAULTS.getDefaultSigner()
3943
})
4044
}
4145
}

packages/siwx/src/core/SIWXConfig.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@ import type {
55
SIWXSession
66
} from '@reown/appkit-controllers'
77

8+
import DefaultSigner from '../signers/DefaultSigner.js'
89
import type { SIWXMessenger } from './SIWXMessenger.js'
10+
import type { SIWXSigner } from './SIWXSigner.js'
911
import type { SIWXStorage } from './SIWXStorage.js'
1012
import type { SIWXVerifier } from './SIWXVerifier.js'
1113

@@ -17,6 +19,7 @@ export abstract class SIWXConfig implements SIWXConfigInterface {
1719
private messenger: SIWXMessenger
1820
private verifiers: SIWXVerifier[]
1921
private storage: SIWXStorage
22+
public signer: SIWXSigner
2023

2124
public required: boolean
2225

@@ -25,6 +28,7 @@ export abstract class SIWXConfig implements SIWXConfigInterface {
2528
this.verifiers = params.verifiers
2629
this.storage = params.storage
2730
this.required = params.required ?? true
31+
this.signer = params.signer || new DefaultSigner()
2832
}
2933

3034
/**
@@ -133,6 +137,16 @@ export abstract class SIWXConfig implements SIWXConfigInterface {
133137
getRequired() {
134138
return this.required
135139
}
140+
141+
public signMessage({
142+
message
143+
}: {
144+
message: string
145+
chainId: string
146+
accountAddress: string
147+
}): Promise<string> {
148+
return this.signer.signMessage(message)
149+
}
136150
}
137151

138152
export namespace SIWXConfig {
@@ -157,5 +171,10 @@ export namespace SIWXConfig {
157171
* @default true
158172
*/
159173
required?: boolean
174+
175+
/**
176+
* The signer handler to sign the message. If not provided, a signature request will be made to the wallet.
177+
*/
178+
signer?: SIWXSigner
160179
}
161180
}

0 commit comments

Comments
 (0)