Skip to content

Commit

Permalink
abi caching
Browse files Browse the repository at this point in the history
  • Loading branch information
nsjames committed Jun 20, 2018
1 parent 632f1d8 commit 0acb9be
Show file tree
Hide file tree
Showing 6 changed files with 113 additions and 9 deletions.
10 changes: 10 additions & 0 deletions src/background.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ export default class Background {
case InternalMessageTypes.REQUEST_GET_VERSION: Background.requestGetVersion(sendResponse); break;
case InternalMessageTypes.REQUEST_VERSION_UPDATE: Background.requestVersionUpdate(sendResponse, message.payload); break;
case InternalMessageTypes.AUTHENTICATE: Background.authenticate(sendResponse, message.payload); break;
case InternalMessageTypes.ABI_CACHE: Background.abiCache(sendResponse, message.payload); break;
case InternalMessageTypes.SET_PROMPT: Background.setPrompt(sendResponse, message.payload); break;
case InternalMessageTypes.GET_PROMPT: Background.getPrompt(sendResponse); break;
}
Expand Down Expand Up @@ -330,6 +331,15 @@ export default class Background {
})
}

static abiCache(sendResponse, payload){
this.lockGuard(sendResponse, async () => {
let abi = null;
if(payload.abiGet) abi = await StorageService.getABI(payload.abiContractName, payload.chainId)
else abi = await StorageService.cacheABI(payload.abiContractName, payload.chainId, payload.abi);
sendResponse(abi);
})
}

/***
* Prompts a request for a transaction signature
* @param sendResponse
Expand Down
7 changes: 7 additions & 0 deletions src/content.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ class Content {
case NetworkMessageTypes.REQUEST_VERSION_UPDATE: this.requestVersionUpdate(nonSyncMessage); break;
case NetworkMessageTypes.AUTHENTICATE: this.authenticate(nonSyncMessage); break;
case NetworkMessageTypes.IDENTITY_FROM_PERMISSIONS: this.identityFromPermissions(nonSyncMessage); break;
case NetworkMessageTypes.ABI_CACHE: this.abiCache(nonSyncMessage); break;
default: stream.send(nonSyncMessage.error(Error.maliciousEvent()), PairingTags.INJECTED)
}
}
Expand All @@ -113,6 +114,12 @@ class Content {
});
}

abiCache(message){
if(!isReady) return;
InternalMessage.payload(InternalMessageTypes.ABI_CACHE, message.payload)
.send().then(res => this.respond(message, res))
}

getOrRequestIdentity(message){
if(!isReady) return;
InternalMessage.payload(InternalMessageTypes.GET_OR_REQUEST_IDENTITY, message.payload)
Expand Down
1 change: 1 addition & 0 deletions src/messages/InternalMessageTypes.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export const PUB_TO_PRIV = 'publicToPrivateKey';
export const DESTROY = 'destroy';

export const IDENTITY_FROM_PERMISSIONS = 'identityFromPermissions';
export const ABI_CACHE = 'abiCache';
export const GET_OR_REQUEST_IDENTITY = 'getOrRequestIdentity';
export const FORGET_IDENTITY = 'forgetIdentity';
export const REQUEST_SIGNATURE = 'requestSignature';
Expand Down
1 change: 1 addition & 0 deletions src/messages/NetworkMessageTypes.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ export const GET_OR_REQUEST_IDENTITY = 'getOrRequestIdentity';
export const IDENTITY_FROM_PERMISSIONS = 'identityFromPermissions';
export const FORGET_IDENTITY = 'forgetIdentity';
export const REQUEST_SIGNATURE = 'requestSignature';
export const ABI_CACHE = 'abiCache';
export const REQUEST_ARBITRARY_SIGNATURE = 'requestArbitrarySignature';
export const REQUEST_ADD_NETWORK = 'requestAddNetwork';
export const REQUEST_VERSION_UPDATE = 'requestVersionUpdate';
Expand Down
73 changes: 68 additions & 5 deletions src/plugins/defaults/eos.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,11 @@ import Account from '../../models/Account'
import AlertMsg from '../../models/alerts/AlertMsg'
import * as Actions from '../../store/constants';
import Eos from 'eosjs'
let {ecc} = Eos.modules;
let {ecc, Fcbuffer} = Eos.modules;
import {IdentityRequiredFields} from '../../models/Identity';
import ObjectHelpers from '../../util/ObjectHelpers'
import * as ricardianParser from 'eos-rc-parser';
import StorageService from '../../services/StorageService'

let networkGetter = new WeakMap();
let messageSender = new WeakMap();
Expand Down Expand Up @@ -230,14 +231,76 @@ export default class EOS extends Plugin {
}


const requestParser = async (_eos, signargs, httpEndpoint, contractAccountName, chainId) => await Promise.all(signargs.transaction.actions.map(async action => {
// This is code duplication from eosjs due to it not being exported.
// https://github.com/EOSIO/eosjs/issues/207
function abiToFcSchema(abi) {
// customTypes
// For FcBuffer
const abiSchema = {}

// convert abi types to Fcbuffer schema
if(abi.types) { // aliases
abi.types.forEach(e => {
abiSchema[e.new_type_name] = e.type
})
}

if(abi.structs) {
abi.structs.forEach(e => {
const fields = {}
for(const field of e.fields) {
fields[field.name] = field.type
}
abiSchema[e.name] = {base: e.base, fields}
if(e.base === '') {
delete abiSchema[e.name].base
}
})
}

return abiSchema
}

import Structs from 'eosjs/lib/structs';

const requestParser = async (_eos, signargs, httpEndpoint, possibleSigner, chainId) => await Promise.all(signargs.transaction.actions.map(async action => {
const eos = _eos({httpEndpoint, chainId});

const abi = await eos.contract(contractAccountName);
const data = abi.fc.fromBuffer(action.name, action.data);
const actionAbi = abi.fc.abi.actions.find(fcAction => fcAction.name === action.name);
const contractAccountName = action.account;

const cachedABI = await messageSender(NetworkMessageTypes.ABI_CACHE, {abiContractName:contractAccountName, abiGet:true, chainId});
console.log('cachedABI', cachedABI);

let abi = null;
if(typeof cachedABI === 'object'){
const schema = abiToFcSchema(cachedABI.abi);
const structs = Structs({defaults:false}, schema);
abi = Object.assign({abi:cachedABI.abi, schema}, structs)
} else {
const contract = await eos.contract(contractAccountName);
if(!contract) throw new Error('Could not get ABI');
abi = contract.fc;
}


const staleAbi = +new Date() - (1000 * 60 * 60 * 24 * 2);
if(typeof cachedABI !== 'object' || cachedABI.timestamp < staleAbi) {
const savableAbi = JSON.parse(JSON.stringify(abi));
delete savableAbi.schema;
delete savableAbi.structs;
delete savableAbi.types;
savableAbi.timestamp = +new Date();

await messageSender(NetworkMessageTypes.ABI_CACHE,
{abiContractName: contractAccountName, abi:savableAbi, abiGet: false, chainId});
}


const data = abi.fromBuffer(action.name, action.data);
const actionAbi = abi.abi.actions.find(fcAction => fcAction.name === action.name);
let ricardian = actionAbi ? actionAbi.ricardian_contract : null;


if(ricardian){
const htmlFormatting = {h1:'div class="ricardian-action"', h2:'div class="ricardian-description"'};
const signer = action.authorization.length === 1 ? action.authorization[0].actor : null;
Expand Down
30 changes: 26 additions & 4 deletions src/services/StorageService.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,35 @@ export default class StorageService {
}

/***
* Backs up the user's Scatter to the Blockchain.
* @param scatter
* Caches an ABI
* @param contractName
* @param chainId
* @param abi
* @returns {Promise}
*/
static backup(scatter){
static cacheABI(contractName, chainId, abi){
console.log('caching abi', abi);
return new Promise((resolve, reject) => {
resolve(true);
apis.storage.local.set({[`abi:${contractName}:${chainId}`]:abi}, () => {
resolve(abi);
});
});
}

/***
* Fetches an ABI from cache
* @param contractName
* @param chainId
* @returns {Promise}
*/
static getABI(contractName, chainId){
return new Promise((resolve, reject) => {
const prop = `abi:${contractName}:${chainId}`;
apis.storage.local.get(prop, (possible) => {
console.log('possible', possible);
if(JSON.stringify(possible) !== '{}') resolve(possible[prop]);
else resolve('no cache');
});
})
}
}

0 comments on commit 0acb9be

Please sign in to comment.