All files index.ts

14.28% Statements 8/56
16.66% Branches 7/42
25% Functions 2/8
14.54% Lines 8/55

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 15845x                           1x       1x 1x 1x                                                                                 1x                                                               1x               2x                                                                                                                
import {
    Canceled,
    Chains,
    Checksum256,
    LoginContext,
    LogoutContext,
    PermissionLevel,
    ResolvedSigningRequest,
    Serializer,
    SigningRequest,
    TransactContext,
    Transaction,
    WalletPluginLoginResponse,
    WalletPluginSignResponse,
} from '@wharfkit/session'
 
import type {ScatterAccount, ScatterIdentity} from 'scatter-ts'
 
export async function getScatter(context): Promise<{scatter: any; connector: any}> {
    if (typeof window === 'undefined') {
        throw new Error(
            'The Scatter protocol requires a browser environment and cannot be used in Node.js.'
        )
    }
 
    const [{Api, JsonRpc}, {ScatterEOS, ScatterJS}] = await Promise.all([
        import('eosjs'),
        import('scatter-ts'),
    ])
 
    // register scatter plugins
    ScatterJS.plugins(new ScatterEOS())
 
    // Setup network
    const url = new URL(context.chain.url)
    const protocol = url.protocol.replace(':', '') === 'https' ? 'https' : 'http'
    const network = ScatterJS.Network.fromJson({
        blockchain: context.chain.name,
        chainId: String(context.chain.id),
        host: url.hostname,
        port: url.port ? Number(url.port) : protocol === 'https' ? 443 : 80,
        protocol,
    })
 
    // Ensure connected
    const connected: boolean = await ScatterJS.connect(context.appName, {network})
    Iif (!connected) {
        throw new Error('Unable to connect with Scatter wallet')
    }
 
    // Establish connector
    const rpc = new JsonRpc(network.fullhost())
    rpc.getRequiredKeys = async () => [] // Hacky way to get around getRequiredKeys
    const connector = ScatterJS.eos(network, Api, {rpc})
 
    return {
        scatter: ScatterJS,
        connector,
    }
}
 
export async function handleLogin(context: LoginContext): Promise<WalletPluginLoginResponse> {
    Iif (!context.ui) {
        throw new Error('No UI available')
    }
 
    // Retrieve translation helper from the UI, passing the app ID
    // const t = context.ui.getTranslate(this.id)
 
    const {scatter} = await getScatter(context)
 
    // login
    const scatterIdentity: ScatterIdentity = await scatter.login()
    Iif (!scatterIdentity || !scatterIdentity.accounts) {
        throw new Error('Unable to retrieve account from Scatter')
    }
    const account: ScatterAccount = scatterIdentity.accounts[0]
 
    let chainId: string
    if (account.chainId) {
        chainId = account.chainId
    } else if (account.blockchain && Object.keys(Chains).includes(account.blockchain)) {
        chainId = Chains[account.blockchain].id
    } else {
        throw new Error(`Unknown chain: ${account.blockchain}`)
    }
 
    return {
        chain: Checksum256.from(chainId),
        permissionLevel: PermissionLevel.from(`${account.name}@${account.authority}`),
    }
}
 
export async function handleLogout(context: LogoutContext): Promise<void> {
    Iif (context.session === undefined) {
        throw new Error('Unknown session')
    }
    const {scatter} = await getScatter({appName: context.appName, chain: context.session.chain})
    await scatter.logout()
}
 
export async function handleSignatureRequest(
    resolved: ResolvedSigningRequest,
    context: TransactContext
): Promise<WalletPluginSignResponse> {
    Iif (!context.ui) {
        throw new Error('No UI available')
    }
 
    // Retrieve translation helper from the UI, passing the app ID
    // const t = context.ui.getTranslate(this.id)
 
    // Get the connector from Scatter
    const {scatter, connector} = await getScatter(context)
 
    const currentIdentity: ScatterIdentity = await scatter.checkLogin()
    Iif (!currentIdentity || !currentIdentity.accounts) {
        throw new Error('Please login first')
    }
 
    // Encode the resolved transaction
    const encoded = Serializer.encode({object: resolved.transaction})
 
    // So eosjs can decode it in its own format
    const decoded = await connector.deserializeTransactionWithActions(encoded.array)
 
    // Call transact on the connector
    const response = await connector.transact(decoded, {
        broadcast: false,
    })
 
    Iif (!response.serializedTransaction) {
        throw new Canceled('User Canceled request')
    }
 
    // Get the response back (since the wallet may have modified the transaction)
    const modified = Serializer.decode({
        data: response.serializedTransaction,
        type: Transaction,
    })
 
    // Create the new request and resolve it
    const modifiedRequest = await SigningRequest.create(
        {
            transaction: modified,
        },
        context.esrOptions
    )
    const abis = await modifiedRequest.fetchAbis(context.abiCache)
    const modifiedResolved = modifiedRequest.resolve(abis, context.permissionLevel)
 
    // Return the modified request and the signatures from the wallet
    return {
        signatures: response.signatures,
        resolved: modifiedResolved,
    }
}