Skip to content

Commit

Permalink
feat/608 - Support memo, use native token (#611)
Browse files Browse the repository at this point in the history
* fix: balances should support native token properly

* feat: adding memo field

* fix: adding memo to Tx

* fix: make bond form legible

* fix: version bump for next release
  • Loading branch information
jurevans authored Feb 6, 2024
1 parent 8b3572d commit bda16c1
Show file tree
Hide file tree
Showing 36 changed files with 284 additions and 182 deletions.
2 changes: 1 addition & 1 deletion apps/extension/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@namada/extension",
"version": "0.2.3",
"version": "0.2.4",
"description": "Namada Browser Extension",
"repository": "https://github.com/anoma/namada-interface/",
"author": "Heliax Dev <[email protected]>",
Expand Down
30 changes: 30 additions & 0 deletions apps/extension/src/background/chains/service.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
import { chains } from "@namada/chains";
import { Query } from "@namada/shared";
import { KVStore } from "@namada/storage";
import { Chain } from "@namada/types";
import { ExtensionBroadcaster } from "extension";

const {
NAMADA_INTERFACE_NAMADA_TOKEN:
tokenAddress = "tnam1qxgfw7myv4dh0qna4hq0xdg6lx77fzl7dcem8h7e",
} = process.env;

export const CHAINS_KEY = "chains";

export class ChainsService {
Expand All @@ -16,6 +22,15 @@ export class ChainsService {
if (!chain) {
// Initialize default chain in storage
const defaultChain = chains.namada;
const {
currency: { address },
} = defaultChain;
if (!address) {
const query = new Query(defaultChain.rpc);
const nativeToken = await query.query_native_token();
defaultChain.currency.address = nativeToken || tokenAddress;
}

await this.chainsStore.set(CHAINS_KEY, defaultChain);
return defaultChain;
}
Expand All @@ -27,10 +42,25 @@ export class ChainsService {
if (!chain) {
throw new Error("No chain found!");
}
let {
currency: { address },
} = chain;

// Attempt to fetch native token, fallback to env
if (!address) {
const query = new Query(chain.rpc);
const nativeToken = await query.query_native_token();
address = nativeToken || tokenAddress;
}

await this.chainsStore.set(CHAINS_KEY, {
...chain,
chainId,
rpc: url,
currency: {
...chain.currency,
address,
},
});
this.broadcaster.updateNetwork();
}
Expand Down
1 change: 1 addition & 0 deletions apps/extension/src/background/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ const init = new Promise<void>(async (resolve) => {
const keyRingService = new KeyRingService(
vaultService,
sdkService,
chainsService,
utilityStore,
connectedTabsStore,
extensionStore,
Expand Down
4 changes: 2 additions & 2 deletions apps/extension/src/background/keyring/handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -225,8 +225,8 @@ const handleQueryDefaultAccountMsg: (
const handleQueryBalancesMsg: (
service: KeyRingService
) => InternalHandler<QueryBalancesMsg> = (service) => {
return async (_, msg) => {
return await service.queryBalances(msg.owner);
return async (_, { owner, tokens }) => {
return await service.queryBalances(owner, tokens);
};
};

Expand Down
9 changes: 3 additions & 6 deletions apps/extension/src/background/keyring/keyring.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ import {
SubmitUnbondMsgValue,
SubmitVoteProposalMsgValue,
SubmitWithdrawMsgValue,
Tokens,
TransferMsgValue,
} from "@namada/types";
import {
Expand Down Expand Up @@ -879,15 +878,13 @@ export class KeyRing {
}

async queryBalances(
owner: string
owner: string,
tokens: string[]
): Promise<{ token: string; amount: string }[]> {
const query = await this.sdkService.getQuery();
const tokenAddresses: string[] = Object.values(Tokens)
.filter((token) => token.address)
.map(({ address }) => address);

try {
return (await query.query_balance(owner, tokenAddresses)).map(
return (await query.query_balance(owner, tokens)).map(
([token, amount]: [string, string]) => {
return {
token,
Expand Down
24 changes: 20 additions & 4 deletions apps/extension/src/background/keyring/service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
} from "@namada/types";
import { Result, truncateInMiddle } from "@namada/utils";

import { ChainsService } from "background/chains";
import {
createOffscreenWithTxWorker,
hasOffscreenDocument,
Expand Down Expand Up @@ -39,12 +40,18 @@ import {
} from "./types";
import { syncTabs, updateTabStorage } from "./utils";

const {
NAMADA_INTERFACE_NAMADA_TOKEN:
tokenAddress = "tnam1qxgfw7myv4dh0qna4hq0xdg6lx77fzl7dcem8h7e",
} = process.env;

export class KeyRingService {
private _keyRing: KeyRing;

constructor(
protected readonly vaultService: VaultService,
protected readonly sdkService: SdkService,
protected readonly chainsService: ChainsService,
protected readonly utilityStore: KVStore<UtilityStore>,
protected readonly connectedTabsStore: KVStore<TabStore[]>,
protected readonly extensionStore: KVStore<number>,
Expand Down Expand Up @@ -260,6 +267,9 @@ export class KeyRingService {
const offscreenDocumentPath = "offscreen.html";
const routerId = await getNamadaRouterId(this.extensionStore);
const rpc = await this.sdkService.getRpc();
const {
currency: { address: nativeToken = tokenAddress },
} = await this.chainsService.getChain();

if (!(await hasOffscreenDocument(offscreenDocumentPath))) {
await createOffscreenWithTxWorker(offscreenDocumentPath);
Expand All @@ -269,7 +279,7 @@ export class KeyRingService {
type: SUBMIT_TRANSFER_MSG_TYPE,
target: OFFSCREEN_TARGET,
routerId,
data: { transferMsg, txMsg, msgId, signingKey, rpc },
data: { transferMsg, txMsg, msgId, signingKey, rpc, nativeToken },
});

if (result?.error) {
Expand All @@ -286,13 +296,18 @@ export class KeyRingService {
signingKey: SigningKey
): Promise<void> {
const rpc = await this.sdkService.getRpc();
const {
currency: { address: nativeToken = tokenAddress },
} = await this.chainsService.getChain();

initSubmitTransferWebWorker(
{
transferMsg,
txMsg,
msgId,
signingKey,
rpc,
nativeToken,
},
this.handleTransferCompleted.bind(this)
);
Expand Down Expand Up @@ -438,14 +453,15 @@ export class KeyRingService {
}

async queryBalances(
address: string
owner: string,
tokens: string[]
): Promise<{ token: string; amount: string }[]> {
const account = await this.vaultService.findOneOrFail<AccountStore>(
KEYSTORE_KEY,
"address",
address
owner
);
return this._keyRing.queryBalances(account.public.owner);
return this._keyRing.queryBalances(account.public.owner, tokens);
}

async queryPublicKey(address: string): Promise<string | undefined> {
Expand Down
11 changes: 9 additions & 2 deletions apps/extension/src/background/sdk/service.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
import { Query, Sdk } from "@namada/shared";
import { ChainsService } from "background/chains";

const {
NAMADA_INTERFACE_NAMADA_TOKEN:
tokenAddress = "tnam1qxgfw7myv4dh0qna4hq0xdg6lx77fzl7dcem8h7e",
} = process.env;

export class SdkService {
constructor(protected readonly chainsService: ChainsService) {}
constructor(protected readonly chainsService: ChainsService) { }

public async getRpc(): Promise<string> {
// Pull chain config from store, as the RPC value may have changed:
Expand All @@ -17,7 +22,9 @@ export class SdkService {

async getSdk(): Promise<Sdk> {
const rpc = await this.getRpc();
return new Sdk(rpc);
const chain = await this.chainsService.getChain();

return new Sdk(rpc, chain.currency.address || tokenAddress);
}

async getQuery(): Promise<Query> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,11 @@ import {
const {
signingKey: { privateKey, xsk },
rpc,
nativeToken,
} = data;
let txMsg = fromBase64(data.txMsg);

const sdk = new Sdk(rpc);
const sdk = new Sdk(rpc, nativeToken);
await sdk.load_masp_params();
// For transparent transactions we have to reveal the public key.
if (privateKey) {
Expand Down
1 change: 1 addition & 0 deletions apps/extension/src/background/web-workers/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export type SubmitTransferMessageData = {
msgId: string;
signingKey: SigningKey;
rpc: string;
nativeToken: string;
};

export const INIT_MSG = "init";
Expand Down
9 changes: 5 additions & 4 deletions apps/extension/src/provider/InjectedNamada.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {
BalancesProps,
Chain,
DerivedAccount,
Namada as INamada,
Expand All @@ -12,7 +13,7 @@ import { InjectedProxy } from "./InjectedProxy";
import { Signer } from "./Signer";

export class InjectedNamada implements INamada {
constructor(private readonly _version: string) {}
constructor(private readonly _version: string) { }

public async connect(): Promise<void> {
return await InjectedProxy.requestMethod<string, void>("connect");
Expand Down Expand Up @@ -47,12 +48,12 @@ export class InjectedNamada implements INamada {
}

public async balances(
owner: string
props: BalancesProps
): Promise<{ token: string; amount: string }[]> {
return await InjectedProxy.requestMethod<
string,
BalancesProps,
{ token: string; amount: string }[]
>("balances", owner);
>("balances", props);
}

public async getChain(): Promise<Chain | undefined> {
Expand Down
6 changes: 4 additions & 2 deletions apps/extension/src/provider/Namada.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {
BalancesProps,
Chain,
DerivedAccount,
Namada as INamada,
Expand Down Expand Up @@ -103,11 +104,12 @@ export class Namada implements INamada {
}

public async balances(
owner: string
props: BalancesProps
): Promise<{ token: string; amount: string }[] | undefined> {
const { owner, tokens } = props;
return await this.requester?.sendMessage(
Ports.Background,
new QueryBalancesMsg(owner)
new QueryBalancesMsg(owner, tokens)
);
}

Expand Down
9 changes: 6 additions & 3 deletions apps/extension/src/provider/messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ export class GetChainMsg extends Message<Chain> {
super();
}

validate(): void {}
validate(): void { }

route(): string {
return Route.Chains;
Expand Down Expand Up @@ -125,12 +125,15 @@ export class QueryBalancesMsg extends Message<
return MessageType.QueryBalances;
}

constructor(public readonly owner: string) {
constructor(
public readonly owner: string,
public readonly tokens: string[]
) {
super();
}

validate(): void {
return;
validateProps(this, ["owner", "tokens"]);
}

route(): string {
Expand Down
3 changes: 2 additions & 1 deletion apps/extension/src/test/init.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ const cryptoMemory = require("@namada/crypto").__wasm.memory;
export class KVStoreMock<T> implements KVStore<T> {
private storage: { [key: string]: T | null } = {};

constructor(readonly _prefix: string) {}
constructor(readonly _prefix: string) { }

get<U extends T>(key: string): Promise<U | undefined> {
return new Promise((resolve) => {
Expand Down Expand Up @@ -114,6 +114,7 @@ export const init = async (): Promise<{
const keyRingService = new KeyRingService(
vaultService,
sdkService,
chainsService,
utilityStore,
connectedTabsStore,
extStore,
Expand Down
1 change: 1 addition & 0 deletions apps/namada-interface/.env.sample
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

# NAMADA
NAMADA_INTERFACE_NAMADA_ALIAS=Namada Testnet
NAMADA_INTERFACE_NAMADA_TOKEN=tnam1qxvg64psvhwumv3mwrrjfcz0h3t3274hwggyzcee
NAMADA_INTERFACE_NAMADA_CHAIN_ID=namada-1.5.32ccad5356012a7
NAMADA_INTERFACE_NAMADA_URL=http://127.0.0.1:26657
NAMADA_INTERFACE_NAMADA_BECH32_PREFIX=atest
Expand Down
Loading

1 comment on commit bda16c1

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.