export const NightlyWallet = () => {}; import { Types } from 'aptos'; import * as SHA3 from 'js-sha3'; import { WalletAccountChangeError, WalletDisconnectionError, WalletNetworkChangeError, WalletNotConnectedError, WalletNotReadyError, WalletSignMessageError, WalletSignTransactionError } from '../WalletProviders/errors'; import { AccountKeys, BaseWalletAdapter, NetworkInfo, scopePollingDetectionStrategy, WalletAdapterNetwork, WalletName, WalletReadyState } from './BaseAdapter'; export class AptosPublicKey { private readonly hexString: string; static default() { return new AptosPublicKey('0'.repeat(64)); } address() { const hash = SHA3.sha3_256.create(); hash.update(Buffer.from(this.asPureHex(), 'hex')); hash.update('\x00'); return '0x' + hash.hex(); } asUint8Array() { return new Uint8Array(Buffer.from(this.asPureHex(), 'hex')); } asString() { return this.hexString; } asPureHex() { return this.hexString.substr(2); } constructor(hexString: string) { if (hexString.startsWith('0x')) { this.hexString = hexString; } else { this.hexString = `0x${hexString}`; } } } interface AptosNightly { publicKey: AptosPublicKey; constructor(eventMap: Map any>); connect(onDisconnect?: () => void, eagerConnect?: boolean): Promise; disconnect(): Promise; signTransaction: ( transaction: Types.TransactionPayload, submit: boolean ) => Promise; signAllTransactions: (transaction: Types.TransactionPayload[]) => Promise; signMessage(msg: string): Promise; network(): Promise<{ api: string; chainId: number; network: string }>; } interface NightlyWindow extends Window { nightly?: { aptos: AptosNightly; }; } declare const window: NightlyWindow; export const NightlyWalletName = 'Nightly' as WalletName<'Nightly'>; export interface NightlyWalletAdapterConfig { provider?: AptosNightly; // network?: WalletAdapterNetwork; timeout?: number; } export class NightlyWalletAdapter extends BaseWalletAdapter { name = NightlyWalletName; url = 'https://chrome.google.com/webstore/detail/nightly/fiikommddbeccaoicoejoniammnalkfa/related?hl=en&authuser=0'; icon = 'https://lh3.googleusercontent.com/_feXM9qulMM5w9BYMLzMpZrxW2WlBmdyg3SbETIoRsHdAD9PANnLCEPabC7lzEK0N8fOyyvFkY3746jk8l73zUErxhU=w128-h128-e365-rj-sc0x00ffffff'; protected _provider: AptosNightly | undefined; protected _network: WalletAdapterNetwork; protected _chainId: string; protected _api: string; protected _timeout: number; protected _readyState: WalletReadyState = typeof window === 'undefined' || typeof document === 'undefined' ? WalletReadyState.Unsupported : WalletReadyState.NotDetected; protected _connecting: boolean; protected _wallet: { publicKey?: string; address?: string; authKey?: string; isConnected: boolean; } | null; constructor({ // provider, // network = WalletAdapterNetwork.Testnet, timeout = 10000 }: NightlyWalletAdapterConfig = {}) { super(); this._provider = typeof window !== 'undefined' ? window.nightly?.aptos : undefined; this._network = undefined; this._timeout = timeout; this._connecting = false; this._wallet = null; if (typeof window !== 'undefined' && this._readyState !== WalletReadyState.Unsupported) { scopePollingDetectionStrategy(() => { if (window.nightly?.aptos) { this._readyState = WalletReadyState.Installed; this.emit('readyStateChange', this._readyState); return true; } return false; }); } } get publicAccount(): AccountKeys { return { publicKey: this._wallet?.publicKey || null, address: this._wallet?.address || null, authKey: this._wallet?.authKey || null }; } get network(): NetworkInfo { return { name: this._network, api: this._api, chainId: this._chainId }; } get connecting(): boolean { return this._connecting; } get connected(): boolean { return !!this._wallet?.isConnected; } get readyState(): WalletReadyState { return this._readyState; } async connect(): Promise { try { if (this.connected || this.connecting) return; if ( !( this._readyState === WalletReadyState.Loadable || this._readyState === WalletReadyState.Installed ) ) throw new WalletNotReadyError(); this._connecting = true; const provider = this._provider || window.nightly?.aptos; const publicKey = await provider?.connect(() => { this._wallet = null; this.emit('disconnect'); }); this._wallet = { publicKey: publicKey?.asString(), address: publicKey?.address(), isConnected: true }; this.emit('connect', this._wallet.publicKey || ''); const networkData = await provider?.network(); this._chainId = networkData?.chainId.toString(); this._api = networkData?.api; this._network = networkData?.network.toLocaleLowerCase() as WalletAdapterNetwork; } catch (error: any) { this.emit('error', error); throw error; } finally { this._connecting = false; } } async disconnect(): Promise { const wallet = this._wallet; if (wallet) { this._wallet = null; try { const provider = this._provider || window.nightly?.aptos; await provider?.disconnect(); } catch (error: any) { this.emit('error', new WalletDisconnectionError(error?.message, error)); } } this.emit('disconnect'); } async signTransaction(payload: Types.TransactionPayload): Promise { try { const wallet = this._wallet; if (!wallet) throw new WalletNotConnectedError(); try { const provider = this._provider || window.nightly?.aptos; const response = await provider?.signTransaction(payload, false); if (response) { return response as Uint8Array; } else { throw new Error('Transaction failed'); } } catch (error: any) { throw new WalletSignTransactionError(error?.message, error); } } catch (error: any) { this.emit('error', error); throw error; } } async signAllTransaction(payload: Types.TransactionPayload[]): Promise { try { const wallet = this._wallet; if (!wallet) throw new WalletNotConnectedError(); try { const provider = this._provider || window.nightly?.aptos; const response = await provider?.signAllTransactions(payload); if (response) { return response; } else { throw new Error('Transaction failed'); } } catch (error: any) { throw new WalletSignTransactionError(error?.message, error); } } catch (error: any) { this.emit('error', error); throw error; } } async signAndSubmitTransaction(tx: Types.TransactionPayload): Promise { try { const wallet = this._wallet; if (!wallet) throw new WalletNotConnectedError(); try { const provider = this._provider || window.nightly?.aptos; const response = await provider?.signTransaction(tx, true); if (response) { return response as Types.PendingTransaction; } else { throw new Error('Transaction failed'); } } catch (error: any) { const errMsg = error instanceof Error ? error.message : error.response.data.message; throw new WalletSignTransactionError(errMsg); } } catch (error: any) { this.emit('error', error); throw error; } } async signMessage(message: string): Promise { try { const wallet = this._wallet; const provider = this._provider || window.nightly.aptos; if (!wallet || !provider) throw new WalletNotConnectedError(); const response = await provider?.signMessage(message); if (response) { return Buffer.from(response).toString('hex'); } else { throw new Error('Sign Message failed'); } } catch (error: any) { const errMsg = error.message; this.emit('error', new WalletSignMessageError(errMsg)); throw error; } } async onAccountChange(): Promise { try { const wallet = this._wallet; const provider = this._provider || window.nightly.aptos; if (!wallet || !provider) throw new WalletNotConnectedError(); //To be implemented } catch (error: any) { const errMsg = error.message; this.emit('error', new WalletAccountChangeError(errMsg)); throw error; } } async onNetworkChange(): Promise { try { const wallet = this._wallet; const provider = this._provider || window.nightly.aptos; if (!wallet || !provider) throw new WalletNotConnectedError(); //To be implemented } catch (error: any) { const errMsg = error.message; this.emit('error', new WalletNetworkChangeError(errMsg)); throw error; } } }