forked from MystenLabs/sui
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[wallet-standard] Introduce wallet-standard package for wallet develo…
…pers (MystenLabs#4925)
- Loading branch information
1 parent
852b937
commit 5ac98bc
Showing
51 changed files
with
1,408 additions
and
559 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"@mysten/wallet-adapter-base": minor | ||
--- | ||
|
||
Add new icon property to the base adapter. Introduce a WalletAdapterProvider API, which can be used to dynamically provide multiple wallet adapters. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"@mysten/wallet-adapter-sui-wallet": minor | ||
--- | ||
|
||
Mark wallet-adapter-sui-wallet as legacy, in favor of the standardized wallet adapter. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
--- | ||
"@mysten/wallet-adapter-all-wallets": minor | ||
"@mysten/wallet-adapter-base": minor | ||
"@mysten/wallet-adapter-mock-wallet": minor | ||
"@mysten/wallet-adapter-sui-wallet": minor | ||
"@mysten/wallet-adapter-wallet-standard": minor | ||
"@mysten/wallet-adapter-react": minor | ||
"@mysten/wallet-adapter-react-ui": minor | ||
"@mysten/wallet-standard": minor | ||
--- | ||
|
||
Introduce new wallet adapter based on the Wallet Standard. This wallet adapter automatically detects wallets that adhere to the standard interface. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"@mysten/wallet-standard": minor | ||
--- | ||
|
||
Introduce new "wallet-standard" package which can be used to build wallets that are compatible with the Wallet Standard. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"@mysten/wallet-adapter-all-wallets": patch | ||
--- | ||
|
||
Add support for standard wallet adapter. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
183 changes: 183 additions & 0 deletions
183
apps/wallet/src/dapp-interface/WalletStandardInterface.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,183 @@ | ||
// Copyright (c) Mysten Labs, Inc. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
import { | ||
SUI_CHAINS, | ||
ReadonlyWalletAccount, | ||
type SuiSignAndExecuteTransactionFeature, | ||
type SuiSignAndExecuteTransactionMethod, | ||
type ConnectFeature, | ||
type ConnectMethod, | ||
type Wallet, | ||
type EventsFeature, | ||
type EventsOnMethod, | ||
type EventsListeners, | ||
} from '@mysten/wallet-standard'; | ||
import mitt, { type Emitter } from 'mitt'; | ||
import { filter, map, type Observable } from 'rxjs'; | ||
|
||
import icon from '../manifest/icons/sui-icon-128.png'; | ||
import { mapToPromise } from './utils'; | ||
import { createMessage } from '_messages'; | ||
import { WindowMessageStream } from '_messaging/WindowMessageStream'; | ||
import { type Payload } from '_payloads'; | ||
import { | ||
type AcquirePermissionsRequest, | ||
type AcquirePermissionsResponse, | ||
ALL_PERMISSION_TYPES, | ||
} from '_payloads/permissions'; | ||
|
||
import type { GetAccount } from '_payloads/account/GetAccount'; | ||
import type { GetAccountResponse } from '_payloads/account/GetAccountResponse'; | ||
import type { | ||
ExecuteTransactionRequest, | ||
ExecuteTransactionResponse, | ||
} from '_payloads/transactions'; | ||
|
||
type WalletEventsMap = { | ||
[E in keyof EventsListeners]: Parameters<EventsListeners[E]>[0]; | ||
}; | ||
|
||
// TODO: rebuild event interface with Mitt. | ||
export class SuiWallet implements Wallet { | ||
readonly #events: Emitter<WalletEventsMap>; | ||
readonly #version = '1.0.0' as const; | ||
readonly #name = 'Sui Wallet' as const; | ||
#account: ReadonlyWalletAccount | null; | ||
#messagesStream: WindowMessageStream; | ||
|
||
get version() { | ||
return this.#version; | ||
} | ||
|
||
get name() { | ||
return this.#name; | ||
} | ||
|
||
get icon() { | ||
// TODO: Improve this with ideally a vector logo. | ||
// eslint-disable-next-line @typescript-eslint/no-explicit-any | ||
return icon as any; | ||
} | ||
|
||
get chains() { | ||
// TODO: Extract chain from wallet: | ||
return SUI_CHAINS; | ||
} | ||
|
||
get features(): ConnectFeature & | ||
EventsFeature & | ||
SuiSignAndExecuteTransactionFeature { | ||
return { | ||
'standard:connect': { | ||
version: '1.0.0', | ||
connect: this.#connect, | ||
}, | ||
'standard:events': { | ||
version: '1.0.0', | ||
on: this.#on, | ||
}, | ||
'sui:signAndExecuteTransaction': { | ||
version: '1.0.0', | ||
signAndExecuteTransaction: this.#signAndExecuteTransaction, | ||
}, | ||
}; | ||
} | ||
|
||
get accounts() { | ||
return this.#account ? [this.#account] : []; | ||
} | ||
|
||
constructor() { | ||
this.#events = mitt(); | ||
this.#account = null; | ||
this.#messagesStream = new WindowMessageStream( | ||
'sui_in-page', | ||
'sui_content-script' | ||
); | ||
|
||
this.#connected(); | ||
} | ||
|
||
#on: EventsOnMethod = (event, listener) => { | ||
this.#events.on(event, listener); | ||
return () => this.#events.off(event, listener); | ||
}; | ||
|
||
#connected = async () => { | ||
const accounts = await mapToPromise( | ||
this.#send<GetAccount, GetAccountResponse>({ | ||
type: 'get-account', | ||
}), | ||
(response) => response.accounts | ||
); | ||
|
||
const [address] = accounts; | ||
|
||
if (address) { | ||
const account = this.#account; | ||
if (!account || account.address !== address) { | ||
this.#account = new ReadonlyWalletAccount({ | ||
address, | ||
// TODO: Expose public key instead of address: | ||
publicKey: new Uint8Array(), | ||
chains: SUI_CHAINS, | ||
features: [ | ||
'sui:signAndExecuteTransaction', | ||
'standard:signMessage', | ||
], | ||
}); | ||
this.#events.emit('change', { accounts: this.accounts }); | ||
} | ||
} | ||
}; | ||
|
||
#connect: ConnectMethod = async (input) => { | ||
if (!input?.silent) { | ||
await mapToPromise( | ||
this.#send< | ||
AcquirePermissionsRequest, | ||
AcquirePermissionsResponse | ||
>({ | ||
type: 'acquire-permissions-request', | ||
permissions: ALL_PERMISSION_TYPES, | ||
}), | ||
(response) => response.result | ||
); | ||
} | ||
|
||
await this.#connected(); | ||
|
||
return { accounts: this.accounts }; | ||
}; | ||
|
||
#signAndExecuteTransaction: SuiSignAndExecuteTransactionMethod = async ( | ||
input | ||
) => { | ||
return mapToPromise( | ||
this.#send<ExecuteTransactionRequest, ExecuteTransactionResponse>({ | ||
type: 'execute-transaction-request', | ||
transaction: { | ||
type: 'v2', | ||
data: input.transaction, | ||
}, | ||
}), | ||
(response) => response.result | ||
); | ||
}; | ||
|
||
#send< | ||
RequestPayload extends Payload, | ||
ResponsePayload extends Payload | void = void | ||
>( | ||
payload: RequestPayload, | ||
responseForID?: string | ||
): Observable<ResponsePayload> { | ||
const msg = createMessage(payload, responseForID); | ||
this.#messagesStream.send(msg); | ||
return this.#messagesStream.messages.pipe( | ||
filter(({ id }) => id === msg.id), | ||
map((msg) => msg.payload as ResponsePayload) | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
// Copyright (c) Mysten Labs, Inc. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
import { lastValueFrom, map, take, type Observable } from 'rxjs'; | ||
|
||
import { isErrorPayload, type Payload } from '_payloads'; | ||
|
||
export function mapToPromise<T extends Payload, R>( | ||
stream: Observable<T>, | ||
project: (value: T) => R | ||
) { | ||
return lastValueFrom( | ||
stream.pipe( | ||
take<T>(1), | ||
map<T, R>((response) => { | ||
if (isErrorPayload(response)) { | ||
// TODO: throw proper error | ||
throw new Error(response.message); | ||
} | ||
return project(response); | ||
}) | ||
) | ||
); | ||
} |
Oops, something went wrong.