orbs-network/orbs-client-sdk-javascript

Initial wallet architecture

netoneko opened this issue · 3 comments

TODO: outline a wallet architecture, supposedly modeled after Metamask Ethereum Provider.

The whole thing boils down to these signature calls: https://github.com/orbs-network/orbs-client-sdk-javascript/blob/master/src/crypto/Signature.ts

They should be extracted to an adapter, which would make it a 2.0 SDK.

interface Signer {
  getPublicKey(): Promise<Uint8Array>;
  signEd25519(data: Uint8Array): Promise<Uint8Array>;
}

interface Account extends Signer {
  getName(): Promise<string>;
  _setName(name: string); // Private method of extension

  getDescription(): Promise<string>;
  _setDescription(name: string); // Private method of extension

  getAddress(): Promise<string>;
  isCompromised(): bool // in case we want to filter out compromised keys

  // Private method of extension
  _lockSigner(); // locks the account, disabling Signer.signEd25519 method
  _unlockSigner(); // unlocks the account, makes all the Signer methods available
}

interface Wallet() {
  async enable(): Account[];
  async addAccount({name: string, description: string, phrase?: string}); // generates a new account and sets name and description, if phrase is available then it is used to restore the private key
}

The sample flow (inspired by Metamask low level flow:

import { Wallet } from "orbs-wallet-javascript";
import { Client, argUint64 } from "orbs-client-javascript";

const wallet = new Wallet({ configOptions });
let accounts;
try {
  accounts = await wallet.enable(); // should open a separate extension window that asks for the password
} catch (e) {
  console.log("Could not initialize wallet: " + e.toString();
  throw e;
}

const account = accounts[0];
const client = new Client("http://localhost:8080", 42, account);

const query = await client.createQuery("ReadOnlyContract", "readInfo");
const queryResult = await client.runQuery(query);

console.log(queryResult.OutputArguments[0]);

const [txid, tx] = client.createTransaction("ModifyStateContract", "add", [argUint64(1)]);
const txResult = await client.SendTransaction(tx);

console.log(txResult.OutputArguments[0]);

I understand that unlocking the singer every time might be a bit of an overkill, so we should discuss if we even need this feature. Metamask does not have it.

I thought we might add it to separate read-only usecase from read-write usecase. I think it's definitely up for discussion, maybe @lbeder could give us a tip if it makes sense.

Updated flow after a meeting with @gilamran