diff --git a/package.json b/package.json index ae496b0..2da7144 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cyano-wallet", - "version": "0.7.16", + "version": "0.7.19", "private": true, "scripts": { "lint": "tslint -p .", @@ -14,7 +14,7 @@ "@bugsnag/plugin-react": "^5.1.0", "@ont-community/hdkey-secp256r1": "^1.0.1", "@ont-community/ontology-ts-sdk-ledger": "^1.0.8", - "@ont-dev/ontology-dapi": "^0.4.9", + "@ont-dev/ontology-dapi": "^0.5.0", "autoprefixer": "7.1.6", "axios": "^0.18.0", "babel-polyfill": "^6.26.0", @@ -31,7 +31,7 @@ "lodash": "^4.17.10", "long": "^4.0.0", "object-assign": "4.1.1", - "ontology-ts-sdk": "^1.0.24", + "ontology-ts-sdk": "^1.1.0", "ontology-ts-test": "^0.2.37", "postcss-flexbugs-fixes": "3.2.0", "promise": "8.0.1", diff --git a/public/manifest.json b/public/manifest.json index 8464ce7..15840dd 100644 --- a/public/manifest.json +++ b/public/manifest.json @@ -4,7 +4,7 @@ "name": "Cyano wallet", "author": "Matus Zamborsky ", "description": "Cyano wallet - an Ontology wallet", - "version": "0.7.16", + "version": "0.7.19", "browser_action": { "default_title": "Open the wallet" diff --git a/src/api/accountApi.ts b/src/api/accountApi.ts index 19094f7..ac9bbd0 100644 --- a/src/api/accountApi.ts +++ b/src/api/accountApi.ts @@ -124,7 +124,7 @@ export function getAccount(wallet: string | Wallet) { const defaultAddress = wallet.defaultAccountAddress; - if (defaultAddress != null) { + if (defaultAddress != null && defaultAddress !== '') { const account = wallet.accounts.find((a) => a.address.toBase58() === defaultAddress); if (account === undefined) { diff --git a/src/api/tokenApi.ts b/src/api/tokenApi.ts index defeefb..2833924 100644 --- a/src/api/tokenApi.ts +++ b/src/api/tokenApi.ts @@ -1,10 +1,12 @@ +export type VmType = 'NEOVM' | 'WASMVM'; export interface OEP4Token { name: string; symbol: string; decimals: number; + vmType: VmType; } export interface OEP4TokenAmount extends OEP4Token { amount: string; -} \ No newline at end of file +} diff --git a/src/background/api/smartContractApi.ts b/src/background/api/smartContractApi.ts index 63c68e2..11b3cec 100644 --- a/src/background/api/smartContractApi.ts +++ b/src/background/api/smartContractApi.ts @@ -212,7 +212,9 @@ function convertParam(parameter: Parameter): Param { // will use ontology-ts-sdk to build script code and it treats ByteArray as hex string; return new Param('', ParameterType.ByteArray, parameter.value); } else if (parameter.type === 'String') { - return new Param('', ParameterType.String, parameter.value); + return new Param('', ParameterType.String, parameter.value) + } else if (parameter.type === 'Long') { + return new Param('', ParameterType.Long, parameter.value) } else if (parameter.type === 'Array') { return new Param('', ParameterType.Array, convertParams(parameter.value)); } else if (parameter.type === 'Map') { diff --git a/src/background/api/tokenApi.ts b/src/background/api/tokenApi.ts index cb464ea..6150495 100644 --- a/src/background/api/tokenApi.ts +++ b/src/background/api/tokenApi.ts @@ -1,10 +1,10 @@ import * as Long from 'long'; -import { CONST, Crypto, Oep4, TransactionBuilder, utils } from 'ontology-ts-sdk'; +import { CONST, Crypto, Oep4, Parameter, ParameterType, TransactionBuilder, utils } from 'ontology-ts-sdk'; import { decryptAccount, getAccount } from 'src/api/accountApi'; import { encodeAmount } from 'src/popup/utils/number'; import { TransferRequest } from 'src/redux/transactionRequests'; import { getWallet } from '../../api/authApi'; -import { OEP4Token } from '../../api/tokenApi'; +import { OEP4Token, VmType } from '../../api/tokenApi'; import { getClient } from '../network'; import { getStore } from '../redux'; @@ -12,34 +12,76 @@ import Address = Crypto.Address; import Oep4TxBuilder = Oep4.Oep4TxBuilder; import { isHexadecimal } from 'src/api/utils'; +const gasPrice = '500'; +const gasLimit = '20000'; export async function getOEP4Token(contract: string): Promise { if (!isHexadecimal(contract)) { throw new Error('Contract is not hexadecimal string'); } - contract = utils.reverseHex(contract); + // TODO 需要支持wasm vm的oep4;转账也要分NEO和wasm; - const builder = new Oep4TxBuilder(new Address(contract)); + const contractAddr = utils.reverseHex(contract); + const builder = new Oep4TxBuilder(new Address(contractAddr)); const client = getClient(); - const nameResponse = await client.sendRawTransaction(builder.queryName().serialize(), true); - const symbolResponse = await client.sendRawTransaction(builder.querySymbol().serialize(), true); - const decimalsResponse = await client.sendRawTransaction(builder.queryDecimals().serialize(), true); + // first get contract json to decide the vmType + const contractJson = await client.getContractJson(contract); + let vmType: VmType = 'NEOVM'; + if (contractJson && contractJson.Error === 0) { + if (contractJson.Result && contractJson.Result.VmType === 3) { + vmType = 'WASMVM'; + } + } + let nameResponse; + let symbolResponse; + let decimalsResponse; + if (vmType === 'WASMVM') { + const tx1 = TransactionBuilder.makeWasmVmInvokeTransaction( + 'name', + [], + new Address(contractAddr), + gasPrice, + gasLimit, + ); + nameResponse = await client.sendRawTransaction(tx1.serialize(), true); + const tx2 = TransactionBuilder.makeWasmVmInvokeTransaction( + 'symbol', + [], + new Address(contractAddr), + gasPrice, + gasLimit, + ); + symbolResponse = await client.sendRawTransaction(tx2.serialize(), true); + const tx3 = TransactionBuilder.makeWasmVmInvokeTransaction( + 'decimals', + [], + new Address(contractAddr), + gasPrice, + gasLimit, + ); + decimalsResponse = await client.sendRawTransaction(tx3.serialize(), true); + } else { + nameResponse = await client.sendRawTransaction(builder.queryName().serialize(), true); + symbolResponse = await client.sendRawTransaction(builder.querySymbol().serialize(), true); + decimalsResponse = await client.sendRawTransaction(builder.queryDecimals().serialize(), true); + } return { decimals: extractNumberResponse(decimalsResponse), name: extractStringResponse(nameResponse), symbol: extractStringResponse(symbolResponse), + vmType, }; } -export async function getTokenBalanceOwn(contract: string) { +export async function getTokenBalanceOwn(contract: string, vmType: VmType) { const state = getStore().getState(); const address = getAccount(state.wallet.wallet!).address; - return getTokenBalance(contract, address); + return getTokenBalance(contract, address, vmType); } -export async function getTokenBalance(contract: string, address: Address) { +export async function getTokenBalance(contract: string, address: Address, vmType: VmType) { const state = getStore().getState(); const token = state.settings.tokens.find((t) => t.contract === contract); @@ -48,12 +90,23 @@ export async function getTokenBalance(contract: string, address: Address) { } contract = utils.reverseHex(contract); - - const builder = new Oep4TxBuilder(new Address(contract)); - const client = getClient(); - const tx = builder.queryBalanceOf(address); - const response = await client.sendRawTransaction(tx.serialize(), true); + let response; + if (vmType === 'WASMVM') { + const params = [new Parameter('param1', ParameterType.Address, address)]; + const tx = TransactionBuilder.makeWasmVmInvokeTransaction( + 'balanceOf', + params, + new Address(contract), + gasPrice, + gasLimit, + ); + response = await client.sendRawTransaction(tx.serialize(), true); + } else { + const builder = new Oep4TxBuilder(new Address(contract)); + const tx = builder.queryBalanceOf(address); + response = await client.sendRawTransaction(tx.serialize(), true); + } return Long.fromString(utils.reverseHex(response.Result.Result), true, 16).toString(); } @@ -66,7 +119,6 @@ export async function transferToken(request: TransferRequest, password: string) if (token === undefined) { throw new Error('OEP-4 token not found.'); } - const contract = utils.reverseHex(token.contract); const builder = new Oep4TxBuilder(new Address(contract)); @@ -75,15 +127,31 @@ export async function transferToken(request: TransferRequest, password: string) const to = new Address(request.recipient); const amount = String(request.amount); - - const tx = builder.makeTransferTx( - from, - to, - encodeAmount(amount, token.decimals), - '500', - `${CONST.DEFAULT_GAS_LIMIT}`, - from, - ); + let tx; + if (token.vmType === 'WASMVM') { + const params = [ + new Parameter('from', ParameterType.Address, from), + new Parameter('to', ParameterType.Address, to), + new Parameter('amount', ParameterType.Long, encodeAmount(amount, token.decimals)) + ]; + tx = TransactionBuilder.makeWasmVmInvokeTransaction( + 'transfer', + params, + new Address(contract), + gasPrice, + `${CONST.DEFAULT_GAS_LIMIT}`, + from + ); + } else { + tx = builder.makeTransferTx( + from, + to, + encodeAmount(amount, token.decimals), + '500', + `${CONST.DEFAULT_GAS_LIMIT}`, + from, + ); + } await TransactionBuilder.signTransactionAsync(tx, privateKey); diff --git a/src/background/balanceProvider.ts b/src/background/balanceProvider.ts index 96139f3..c917f78 100644 --- a/src/background/balanceProvider.ts +++ b/src/background/balanceProvider.ts @@ -37,7 +37,7 @@ export async function refreshBalance(store: GlobalStore) { for (const token of tokens) { try { - const amount = await getTokenBalanceOwn(token.contract); + const amount = await getTokenBalanceOwn(token.contract, token.vmType); tokenBalances.push({ contract: token.contract, amount }); } catch (e) { // tslint:disable-next-line:no-console diff --git a/src/background/redux/settingsReducer.ts b/src/background/redux/settingsReducer.ts index 5e59b46..ec682d2 100644 --- a/src/background/redux/settingsReducer.ts +++ b/src/background/redux/settingsReducer.ts @@ -48,6 +48,7 @@ export const settingsReducer: Reducer = (state = defaultState, ac name: action.name, specification: action.specification, symbol: action.symbol, + vmType: action.vmType }, ], }; diff --git a/src/popup/pages/dashboard/dashboard.tsx b/src/popup/pages/dashboard/dashboard.tsx index f69dcd3..6a41d83 100644 --- a/src/popup/pages/dashboard/dashboard.tsx +++ b/src/popup/pages/dashboard/dashboard.tsx @@ -121,6 +121,7 @@ function prepareTokenAmounts(tokens: TokenState[] = [], items: TokenAmountState[ decimals: token.decimals, name: token.name, symbol: token.symbol, + vmType: token.vmType, }; }); } diff --git a/src/popup/pages/send/sendView.tsx b/src/popup/pages/send/sendView.tsx index 36ae82b..1844c37 100644 --- a/src/popup/pages/send/sendView.tsx +++ b/src/popup/pages/send/sendView.tsx @@ -109,7 +109,7 @@ export const SendView: React.SFC = (props) => ( input={{ ...t.input, value: t.input.value }} error={t.meta.touched && t.meta.invalid} disabled={props.locked || get(formProps.values, 'asset') === undefined} - action={