@pontem/aptos-wallet-adapter
Version:
Wallet adapter with supporting Vue and React
336 lines (290 loc) • 9.3 kB
text/typescript
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<string, (data: any) => any>);
connect(onDisconnect?: () => void, eagerConnect?: boolean): Promise<AptosPublicKey>;
disconnect(): Promise<void>;
signTransaction: (
transaction: Types.TransactionPayload,
submit: boolean
) => Promise<Uint8Array | Types.PendingTransaction>;
signAllTransactions: (transaction: Types.TransactionPayload[]) => Promise<Uint8Array[]>;
signMessage(msg: string): Promise<Uint8Array>;
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<void> {
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<void> {
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<Uint8Array> {
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<Uint8Array[]> {
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<Types.PendingTransaction> {
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<string> {
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<void> {
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<void> {
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;
}
}
}