Skip to content
This repository has been archived by the owner on Aug 26, 2021. It is now read-only.

Commit

Permalink
Android transaction support (#29)
Browse files Browse the repository at this point in the history
* Add transaction support to android

* add wallet test

* add callback host to docs

* fix test

* update package lock

* make request consistent

* Convert input to android request internally

* ident fix

* add 0x to payload

Co-authored-by: hewigovens <360470+hewigovens@users.noreply.github.com>
  • Loading branch information
vcoolish and hewigovens authored Oct 22, 2020
1 parent 768d24a commit a02c06e
Show file tree
Hide file tree
Showing 11 changed files with 6,383 additions and 3,879 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ wallet.signMessage(message, CoinType.ethereum)
sign an Ethereum transaction:

```typescript
// tx should comply TW.Ethereum.Proto.ISigningInput from @trustwallet/wallet-core
const tx = {
toAddress: '0x728B02377230b5df73Aa4E3192E89b6090DD7312',
chainId: Buffer.from('0x01', 'hex'),
Expand Down
23 changes: 12 additions & 11 deletions example/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -90,22 +90,23 @@ class App extends React.Component {

signEthereumTransaction(send: boolean = false) {
console.log('signTransaction send: ' + send);

const tx = {
toAddress: '0x728B02377230b5df73Aa4E3192E89b6090DD7312',
chainId: Buffer.from('0x01', 'hex'),
nonce: this.serializeBigInt('447'),
gasPrice: this.serializeBigInt('2112000000'),
gasLimit: this.serializeBigInt('21000'),
amount: this.serializeBigInt('100000000000000'),
};
this.wallet
?.signTransaction(tx, CoinType.ethereum, send)
.then((result) => {
Alert.alert('Transaction', result);
})
.catch((error) => {
Alert.alert('Error', JSON.stringify(error));
});
amount: this.serializeBigInt('10000'),
payload: Buffer.from("a9059cbb0000000000000000000000000F36f148D6FdEaCD6c765F8f59D4074109E311f0c0000000000000000000000000000000000000000000000000000000000000001", 'hex')
}
this.wallet?.signTransaction(tx, CoinType.ethereum, send)
.then((result) => {
Alert.alert('Transaction', result);
})
.catch((error) => {
Alert.alert('Error', JSON.stringify(error));
});
}

render() {
Expand All @@ -131,7 +132,7 @@ class App extends React.Component {
}}
/>
<Button
title="Ethereum + Cosmos +Binance" onPress={() => {
title="Ethereum + Cosmos + Binance" onPress={() => {
this.requestAccount([
CoinType.ethereum,
CoinType.cosmos,
Expand Down
7,111 changes: 4,293 additions & 2,818 deletions example/package-lock.json

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions example/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
"lint": "eslint . --ext .js,.jsx,.ts,.tsx"
},
"dependencies": {
"@trustwallet/rn-sdk": "0.2.0",
"@trustwallet/wallet-core": "0.0.4",
"@trustwallet/rn-sdk": "0.2.2",
"@trustwallet/wallet-core": "2.3.2",
"buffer": "^5.6.0",
"console": "^0.7.2",
"ethers": "^5.0.3",
Expand Down
51 changes: 50 additions & 1 deletion index.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
import { Linking } from "react-native";
import { Linking, Platform } from "react-native";
import { Buffer } from "buffer";
import {
TrustCommand,
Request,
AccountsRequest,
MessageRequest,
TransactionRequest,
AndroidTransactionRequest,
DAppMetadata,
} from "./lib/commands";
import { TrustError } from "./lib/errors";
import { TW, CoinType } from "@trustwallet/wallet-core";
import { BigNumber } from 'ethers';

class TrustWallet {
callbackScheme: string;
Expand Down Expand Up @@ -99,6 +101,19 @@ class TrustWallet {
coin: CoinType,
send: boolean = false,
meta?: DAppMetadata
): Promise<string> {
if (Platform.OS === "android") {
return this.signAndroidTransaction(input, coin, send);
} else {
return this.signIOSTransaction(input, coin, send, meta);
}
}

private signIOSTransaction(
input: Object,
coin: CoinType,
send: boolean = false,
meta?: DAppMetadata
): Promise<string> {
let data = new Uint8Array(0);
switch (coin) {
Expand All @@ -120,6 +135,39 @@ class TrustWallet {
return this.sendRequest(request);
}

private signAndroidTransaction(
input: Object,
coin: CoinType,
send: boolean
): Promise<string> {
let proto = TW.Ethereum.Proto.SigningInput.create(input);
switch (coin) {
case CoinType.ethereum:
const request = new AndroidTransactionRequest(
coin.toString(),
proto.toAddress,
this.deserializeBigInt(proto.amount) || "0",
this.callbackScheme,
send,
this.genId("tx_"),
this.deserializeBigInt(proto.nonce),
this.deserializeBigInt(proto.gasPrice),
this.deserializeBigInt(proto.gasLimit),
'0x' + Buffer.from(proto.payload).toString("hex")
);
return this.sendRequest(request);
default:
throw new Error("not implemented yet");
}
}

private deserializeBigInt(value?: Uint8Array): string | undefined {
if (!value || value.length === 0) {
return undefined;
}
return BigNumber.from(value).toString();
}

private genId(prefix?: string): string {
this.callbackId++;
return (prefix || "") + this.callbackId;
Expand Down Expand Up @@ -174,6 +222,7 @@ export {
AccountsRequest,
MessageRequest,
TransactionRequest,
AndroidTransactionRequest,
CoinType,
TrustError,
DAppMetadata,
Expand Down
69 changes: 68 additions & 1 deletion lib/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export enum TrustCommand {
requestAccounts = "sdk_get_accounts",
signTransaction = "sdk_sign",
signMessage = "sdk_sign_message",
androidTransaction = "sdk_transaction",
}

/**
Expand Down Expand Up @@ -36,7 +37,7 @@ export namespace TrustCommand {
} else if (id.startsWith("msg_")) {
result = url.query.signature || "";
} else if (id.startsWith("tx_")) {
result = url.query.data || "";
result = url.query.data || url.query.transaction_hash || url.query.transaction_sign || "";
}
return { id, result, error };
}
Expand Down Expand Up @@ -184,6 +185,72 @@ export class TransactionRequest implements Request {
}
}

export class AndroidTransactionRequest implements Request {
coin: string;
toAddress: string;
nonce?: string;
gasPrice?: string;
gasLimit?: string;
amount: string;
meta: string;
id: string = "0";
command: string = TrustCommand.androidTransaction;
callbackScheme: string;
callbackPath: string;
confirmType: string;

constructor(
coin: string,
toAddress: string,
amount: string,
callbackScheme: string,
send: boolean,
callbackId: string,
nonce?: string,
gasPrice?: string,
gasLimit?: string,
meta?: string
) {
this.coin = coin;
this.toAddress = toAddress;
this.nonce = nonce;
this.gasPrice = gasPrice;
this.gasLimit = gasLimit;
this.amount = amount;
this.meta = meta || "";
this.callbackScheme = callbackScheme;
this.callbackPath = TrustCommand.signTransaction;
this.id = callbackId;
if (send) {
this.confirmType = "send";
} else {
this.confirmType = "sign";
}
}

toQuery(): QueryItem[] {
var array: QueryItem[] = [];
array.push({ k: "asset", v: 'c' + this.coin });
array.push({ k: "to", v: this.toAddress });
array.push({ k: "meta", v: this.meta });
if (this.nonce) {
array.push({ k: "nonce", v: this.nonce });
}
if (this.gasPrice) {
array.push({ k: "fee_price", v: this.gasPrice });
}
if (this.gasLimit) {
array.push({ k: "fee_limit", v: this.gasLimit });
}
array.push({ k: "wei_amount", v: this.amount });
array.push({ k: "action", v: "transfer" });
array.push({ k: "confirm_type", v: this.confirmType });
array.push({ k: "callback", v: this.callbackScheme + this.callbackPath });
array.push({ k: "id", v: this.id });
return array;
}
}

export class MessageRequest implements Request {
id: string;
command: string = TrustCommand.signMessage;
Expand Down
Loading

0 comments on commit a02c06e

Please sign in to comment.