-
Notifications
You must be signed in to change notification settings - Fork 59
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(aepp): extract class to connect to wallet from AeSdkAepp
- Loading branch information
Showing
9 changed files
with
245 additions
and
21 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
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
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
import { Network } from './rpc/types'; | ||
import BrowserConnection from './connection/Browser'; | ||
import WalletConnectorFrameBase from './WalletConnectorFrameBase'; | ||
|
||
interface EventsNetworkId { | ||
networkIdChange: (networkId: string) => void; | ||
} | ||
|
||
/** | ||
* Connect to wallet as iframe/web-extension | ||
* @category aepp wallet communication | ||
*/ | ||
export default class WalletConnectorFrame extends WalletConnectorFrameBase<EventsNetworkId> { | ||
#networkId = ''; | ||
|
||
/** | ||
* The last network id reported by wallet | ||
*/ | ||
get networkId(): string { | ||
return this.#networkId; | ||
} | ||
|
||
protected override _updateNetwork(params: Network): void { | ||
this.#networkId = params.networkId; | ||
this.emit('networkIdChange', this.#networkId); | ||
} | ||
|
||
/** | ||
* Connect to wallet | ||
* @param name - Aepp name | ||
* @param connection - Wallet connection object | ||
*/ | ||
static async connect( | ||
name: string, | ||
connection: BrowserConnection, | ||
): Promise<WalletConnectorFrame> { | ||
const connector = new WalletConnectorFrame(); | ||
await WalletConnectorFrame._connect(name, connection, connector, false); | ||
return connector; | ||
} | ||
} |
119 changes: 119 additions & 0 deletions
119
src/aepp-wallet-communication/WalletConnectorFrameBase.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,119 @@ | ||
import EventEmitter from 'eventemitter3'; | ||
import AccountRpc from '../account/Rpc'; | ||
import { Encoded } from '../utils/encoder'; | ||
import { | ||
Accounts, RPC_VERSION, Network, WalletApi, AeppApi, | ||
} from './rpc/types'; | ||
import RpcClient from './rpc/RpcClient'; | ||
import { METHODS, SUBSCRIPTION_TYPES } from './schema'; | ||
import { NoWalletConnectedError } from '../utils/errors'; | ||
import BrowserConnection from './connection/Browser'; | ||
|
||
interface EventsBase { | ||
accountsChange: (accounts: AccountRpc[]) => void; | ||
disconnect: (p: any) => void; | ||
} | ||
|
||
export default abstract class WalletConnectorFrameBase<T extends {}> | ||
extends EventEmitter<EventsBase | T> { | ||
#rpcClient?: RpcClient<WalletApi, AeppApi>; | ||
|
||
#getRpcClient(): RpcClient<WalletApi, AeppApi> { | ||
if (this.#rpcClient == null) throw new NoWalletConnectedError('You are not connected to Wallet'); | ||
return this.#rpcClient; | ||
} | ||
|
||
/** | ||
* Is connected to wallet | ||
*/ | ||
get isConnected(): boolean { | ||
return this.#rpcClient != null; | ||
} | ||
|
||
#accounts: AccountRpc[] = []; | ||
|
||
/** | ||
* Accounts provided by wallet over subscription | ||
*/ | ||
get accounts(): AccountRpc[] { | ||
return this.#accounts; | ||
} | ||
|
||
protected constructor() { | ||
super(); | ||
} | ||
|
||
protected abstract _updateNetwork(params: Network): void; | ||
|
||
#updateAccounts(params: Accounts): void { | ||
const addresses = [...new Set( | ||
[...Object.keys(params.current), ...Object.keys(params.connected)], | ||
)] as Encoded.AccountAddress[]; | ||
this.#accounts = addresses.map((address) => new AccountRpc(this.#getRpcClient(), address)); | ||
this.emit('accountsChange', this.#accounts); | ||
} | ||
|
||
static async _connect( | ||
name: string, | ||
connection: BrowserConnection, | ||
connector: WalletConnectorFrameBase<any>, | ||
connectNode: boolean, | ||
): Promise<void> { | ||
let disconnectParams: any; | ||
|
||
const client = new RpcClient<WalletApi, AeppApi>( | ||
connection, | ||
() => { | ||
connector.#rpcClient = undefined; | ||
connector.#accounts = []; | ||
connector.emit('disconnect', disconnectParams); | ||
}, | ||
{ | ||
[METHODS.updateAddress]: connector.#updateAccounts.bind(connector), | ||
[METHODS.updateNetwork]: connector._updateNetwork.bind(connector), | ||
[METHODS.closeConnection]: (params) => { | ||
disconnectParams = params; | ||
client.connection.disconnect(); | ||
}, | ||
[METHODS.readyToConnect]: () => {}, | ||
}, | ||
); | ||
connector.#rpcClient = client; | ||
const walletInfo = await connector.#rpcClient | ||
.request(METHODS.connect, { name, version: RPC_VERSION, connectNode }); | ||
connector._updateNetwork(walletInfo); | ||
} | ||
|
||
/** | ||
* Disconnect from wallet | ||
*/ | ||
disconnect(): void { | ||
const client = this.#getRpcClient(); | ||
client.notify(METHODS.closeConnection, { reason: 'bye' }); | ||
client.connection.disconnect(); | ||
} | ||
|
||
/** | ||
* Request accounts from wallet | ||
*/ | ||
async getAccounts(): Promise<AccountRpc[]> { | ||
const client = this.#getRpcClient(); | ||
const addresses = await client.request(METHODS.address, undefined); | ||
return addresses.map((address) => new AccountRpc(client, address)); | ||
} | ||
|
||
/** | ||
* Subscribe for wallet accounts, get account updates adding handler to `accountsChange` event | ||
* @param type - Subscription type | ||
* @param value - Should be one of 'current' (the selected account), 'connected' (all) | ||
* @returns Accounts from wallet | ||
*/ | ||
async subscribeAccounts( | ||
type: SUBSCRIPTION_TYPES, | ||
value: 'current' | 'connected', | ||
): Promise<AccountRpc[]> { | ||
const result = await this.#getRpcClient().request(METHODS.subscribeAddress, { type, value }); | ||
this.#updateAccounts(result.address); | ||
return this.#accounts; | ||
} | ||
} |
45 changes: 45 additions & 0 deletions
45
src/aepp-wallet-communication/WalletConnectorFrameWithNode.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,45 @@ | ||
import { Network } from './rpc/types'; | ||
import { RpcConnectionError } from '../utils/errors'; | ||
import Node from '../Node'; | ||
import BrowserConnection from './connection/Browser'; | ||
import WalletConnectorFrameBase from './WalletConnectorFrameBase'; | ||
|
||
interface EventsWithNode { | ||
nodeChange: (node: Node) => void; | ||
} | ||
|
||
/** | ||
* Connect to wallet as iframe/web-extension, asks wallet to provide node url | ||
* In comparison with WalletConnectorFrame, this would work better for decentralized applications | ||
* @category aepp wallet communication | ||
*/ | ||
export default class WalletConnectorFrameWithNode extends WalletConnectorFrameBase<EventsWithNode> { | ||
#node: Node = null as unknown as Node; | ||
|
||
/** | ||
* The node instance provided by wallet | ||
*/ | ||
get node(): Node { | ||
return this.#node; | ||
} | ||
|
||
protected override _updateNetwork(params: Network): void { | ||
if (params.node?.url == null) throw new RpcConnectionError('Missing URLs of the Node'); | ||
this.#node = new Node(params.node.url); | ||
this.emit('nodeChange', this.#node); | ||
} | ||
|
||
/** | ||
* Connect to wallet | ||
* @param name - Aepp name | ||
* @param connection - Wallet connection object | ||
*/ | ||
static async connect( | ||
name: string, | ||
connection: BrowserConnection, | ||
): Promise<WalletConnectorFrameWithNode> { | ||
const connector = new WalletConnectorFrameWithNode(); | ||
await super._connect(name, connection, connector, true); | ||
return connector; | ||
} | ||
} |
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