Skip to content

Commit f1ec7aa

Browse files
authored
feat: use wallet daemon client with webrtc rpc transport (#2)
requires tari-project/tari-dan#943 Implements RpcBackend for webrtc and uses wallet daemon client to communicate over WebRTC to the wallet daemon Package is named `@tariproject/tarijs`
1 parent 8fc2e9d commit f1ec7aa

File tree

13 files changed

+361
-297
lines changed

13 files changed

+361
-297
lines changed

Diff for: .prettierrc

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"printWidth": 120,
3+
"tabWidth": 2,
4+
"useTabs": false,
5+
"semi": true,
6+
"singleQuote": false,
7+
"trailingComma": "all",
8+
"bracketSpacing": true,
9+
"bracketSameLine": false,
10+
"arrowParens": "always",
11+
"endOfLine": "auto"
12+
}

Diff for: example/src/App.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import * as React from 'react';
22
import { Typography, Container, Button, Paper, Stack, Divider, TextField } from '@mui/material';
3-
import { TransactionSubmitRequest } from '../../src/providers';
3+
import { SubmitTransactionRequest } from '../../src/providers';
44
import Header from './Header';
55

66
export default function App() {

Diff for: package-lock.json

+19-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"name": "tari.js",
2+
"name": "@tariproject/tarijs",
33
"version": "0.1.14",
44
"description": "",
55
"main": "./dist/index.js",
@@ -16,6 +16,7 @@
1616
"@rollup/plugin-image": "^3.0.2",
1717
"@types/react": "^18.0.37",
1818
"@types/react-dom": "^18.0.11",
19+
"@tariproject/wallet_jrpc_client": "file:../../tari/dan/clients/javascript/wallet_daemon_client",
1920
"babel-core": "^4.7.16",
2021
"babel-runtime": "^6.26.0",
2122
"qrcode.react": "^3.1.0",

Diff for: src/providers/index.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {Account, TransactionSubmitRequest, TransactionResult, TransactionSubmitResponse} from './types'
1+
import {Account, SubmitTransactionRequest, TransactionResult, SubmitTransactionResponse} from './types'
22

33
export * as walletDaemon from './wallet_daemon'
44
export * as metamask from './metamask'
@@ -9,7 +9,7 @@ export interface TariProvider {
99
isConnected(): boolean;
1010
getAccount(): Promise<Account>;
1111
getSubstate(substate_address: string): Promise<unknown>,
12-
submitTransaction(req: TransactionSubmitRequest): Promise<TransactionSubmitResponse>
12+
submitTransaction(req: SubmitTransactionRequest): Promise<SubmitTransactionResponse>
1313
getTransactionResult(transactionId: string): Promise<TransactionResult>
1414
getTemplateDefinition(template_address: string): Promise<unknown>
1515
}

Diff for: src/providers/metamask/index.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import {TariProvider} from "../index";
2-
import {TransactionSubmitRequest, TransactionResult, TransactionStatus, TransactionSubmitResponse} from "../types";
2+
import {SubmitTransactionRequest, TransactionResult, TransactionStatus, SubmitTransactionResponse} from "../types";
33
import {MetaMaskInpageProvider} from '@metamask/providers';
44
import {connectSnap, getSnap, isFlask, Snap} from "./utils";
55
import {Maybe} from "@metamask/providers/dist/utils";
@@ -77,7 +77,7 @@ export class MetamaskTariProvider implements TariProvider {
7777
return await this.metamaskRequest('getSubstate', { substate_address });
7878
}
7979

80-
async submitTransaction(req: TransactionSubmitRequest): Promise<TransactionSubmitResponse> {
80+
async submitTransaction(req: SubmitTransactionRequest): Promise<SubmitTransactionResponse> {
8181
const params = {
8282
instructions: req.instructions,
8383
fee_instructions: req.fee_instructions,

Diff for: src/providers/types.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11

22
export type SubstateRequirement = {
3-
address: string,
3+
substate_id: string,
44
version?: number | null,
55
};
66

7-
export type TransactionSubmitRequest = {
7+
export type SubmitTransactionRequest = {
88
account_id: number,
99
instructions: object[],
1010
fee_instructions: object[],
@@ -16,7 +16,7 @@ export type TransactionSubmitRequest = {
1616
max_epoch: number | null,
1717
};
1818

19-
export type TransactionSubmitResponse = {
19+
export type SubmitTransactionResponse = {
2020
transaction_id: string;
2121
};
2222

Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
11
export { TariConnection } from "./webrtc";
22

3-
export default function test() {
4-
console.log("test")
5-
}
63

74
export * from './tari_permissions'
85
export * from './provider'

Diff for: src/providers/wallet_daemon/provider.ts

+62-41
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,15 @@
11
import {TariPermissions} from "./tari_permissions";
22
import {TariConnection} from "./webrtc";
33
import {TariProvider} from '../index';
4-
import {TransactionSubmitRequest, TransactionResult, TransactionStatus, TransactionSubmitResponse} from '../types';
4+
import {SubmitTransactionRequest, TransactionResult, TransactionStatus, SubmitTransactionResponse} from '../types';
55
import {Account} from "../types";
6+
import {
7+
WalletDaemonClient,
8+
stringToSubstateId,
9+
Instruction,
10+
TransactionSubmitRequest, SubstateType, SubstatesListRequest
11+
} from "@tariproject/wallet_jrpc_client";
12+
import {WebRtcRpcTransport} from "./webrtc_transport";
613

714
export const WalletDaemonNotConnected = 'WALLET_DAEMON_NOT_CONNECTED';
815
export const Unsupported = 'UNSUPPORTED';
@@ -19,11 +26,11 @@ export type WalletDaemonParameters = {
1926
export class WalletDaemonTariProvider implements TariProvider {
2027
public providerName = "WalletDaemon";
2128
params: WalletDaemonParameters;
22-
connection: TariConnection;
29+
client: WalletDaemonClient;
2330

24-
private constructor(params: WalletDaemonParameters, connection: TariConnection) {
31+
private constructor(params: WalletDaemonParameters, connection: WalletDaemonClient) {
2532
this.params = params;
26-
this.connection = connection;
33+
this.client = connection;
2734
}
2835

2936
static async build(params: WalletDaemonParameters): Promise<WalletDaemonTariProvider> {
@@ -32,49 +39,54 @@ export class WalletDaemonTariProvider implements TariProvider {
3239
allPermissions.addPermissions(params.optionalPermissions);
3340
console.log({allPermissions});
3441
let connection = new TariConnection(params.signalingServerUrl, params.webRtcConfig);
35-
await connection.init(allPermissions, params.onConnection);
36-
return new WalletDaemonTariProvider(params, connection);
42+
const client = WalletDaemonClient.new(WebRtcRpcTransport.new(connection));
43+
await connection.init(allPermissions, (conn) => {
44+
params.onConnection?.();
45+
if (conn.token) {
46+
client.setToken(conn.token);
47+
}
48+
});
49+
return new WalletDaemonTariProvider(params, client);
3750
}
3851

3952
public get token(): string | undefined {
40-
return this.connection.token;
53+
return (this.client.getTransport() as WebRtcRpcTransport).token();
4154
}
4255

4356
public get tokenUrl(): string | undefined {
44-
if (this.connection.token) {
45-
const name = this.params.name && encodeURIComponent(this.params.name) || '';
46-
const token = this.connection.token;
47-
const permissions = JSON.stringify(this.params.permissions);
48-
const optionalPermissions = JSON.stringify(this.params.optionalPermissions);
49-
50-
return `tari://${name}/${token}/${permissions}/${optionalPermissions}`
57+
if (!this.token) {
58+
return undefined;
5159
}
52-
return undefined;
60+
61+
const name = this.params.name && encodeURIComponent(this.params.name) || '';
62+
const token = this.token;
63+
const permissions = JSON.stringify(this.params.permissions);
64+
const optionalPermissions = JSON.stringify(this.params.optionalPermissions);
65+
66+
return `tari://${name}/${token}/${permissions}/${optionalPermissions}`
5367
}
5468

5569
public isConnected(): boolean {
56-
return this.connection.isConnected();
70+
return (this.client.getTransport() as WebRtcRpcTransport).isConnected();
5771
}
5872

5973
public async createFreeTestCoins(): Promise<Account> {
60-
const method = "accounts.create_free_test_coins";
61-
const res = await this.connection.sendMessage(method, this.connection.token, {
62-
account: null,
74+
const res = await this.client.createFreeTestCoins({
75+
account: {Name: "template_web"},
6376
amount: 1000000,
6477
max_fee: null,
6578
key_id: 0
66-
}) as any;
79+
});
6780
return {
6881
account_id: res.account.key_index,
69-
address: res.account.address.Component,
82+
address: (res.account.address as { Component: string }).Component,
7083
public_key: res.public_key,
7184
resources: []
7285
};
7386
}
7487

7588
public async getAccount(): Promise<Account> {
76-
const method = "accounts.get_default";
77-
const {account, public_key} = await this.connection.sendMessage(method, this.connection.token, {}) as any;
89+
const {account, public_key} = await this.client.accountsGetDefault({}) as any;
7890

7991
return {
8092
account_id: account.key_index,
@@ -86,38 +98,37 @@ export class WalletDaemonTariProvider implements TariProvider {
8698
}
8799

88100
public async getAccountBalances(componentAddress: string): Promise<unknown> {
89-
const method = "accounts.get_balances";
90-
const args = {ComponentAddress: componentAddress};
91-
const res = await this.connection.sendMessage(method, this.connection.token, args);
92-
93-
return res;
101+
return await this.client.accountsGetBalances({account: {ComponentAddress: componentAddress}, refresh: true});
94102
}
95103

96-
public async getSubstate(_substate_address: string): Promise<unknown> {
97-
// TODO: the wallet daemon should expose a JRPC method to retrieve any substate
98-
throw Unsupported;
104+
public async getSubstate(substate_id: string): Promise<unknown> {
105+
const substateId = stringToSubstateId(substate_id);
106+
return await this.client.substatesGet({substate_id: substateId});
99107
}
100108

101-
public async submitTransaction(req: TransactionSubmitRequest): Promise<TransactionSubmitResponse> {
109+
public async submitTransaction(req: SubmitTransactionRequest): Promise<SubmitTransactionResponse> {
102110
const params = {
103111
signing_key_index: req.account_id,
104-
fee_instructions: req.fee_instructions,
105-
instructions: req.instructions,
106-
inputs: req.required_substates,
112+
fee_instructions: req.fee_instructions as Instruction[],
113+
instructions: req.instructions as Instruction[],
114+
inputs: req.required_substates.map((s) => ({
115+
// TODO: Hmm The bindings want a SubstateId object, but the wallet only wants a string. Any is used to skip type checking here
116+
substate_id: s.substate_id as any,
117+
version: s.version
118+
})),
107119
override_inputs: false,
108120
is_dry_run: req.is_dry_run,
109121
proof_ids: [],
110122
min_epoch: null,
111123
max_epoch: null,
112-
};
113-
const res = await this.connection.sendMessage<any>("transactions.submit", this.connection.token, params, 10);
124+
} as TransactionSubmitRequest;
125+
const res = await this.client.submitTransaction(params);
114126

115127
return {transaction_id: res.transaction_id};
116128
}
117129

118130
public async getTransactionResult(transactionId: string): Promise<TransactionResult> {
119-
const params = {transaction_id: transactionId};
120-
const res = await this.connection.sendMessage("transactions.get_result", this.connection.token, params) as any;
131+
const res = await this.client.getTransactionResult({transaction_id: transactionId});
121132

122133
return {
123134
transaction_id: transactionId,
@@ -127,8 +138,18 @@ export class WalletDaemonTariProvider implements TariProvider {
127138
}
128139

129140
public async getTemplateDefinition(template_address: string): Promise<unknown> {
130-
const params = {template_address};
131-
return await this.connection.sendMessage("templates.get", this.connection.token, params);
141+
return await this.client.templatesGet({template_address});
142+
}
143+
144+
public async listSubstates(
145+
template: string | null,
146+
substateType: SubstateType | null
147+
) {
148+
const resp = await this.client.substatesList({
149+
filter_by_template: template,
150+
filter_by_type: substateType
151+
} as SubstatesListRequest);
152+
return resp.substates as any[];
132153
}
133154
}
134155

Diff for: src/providers/wallet_daemon/tari_permissions.tsx renamed to src/providers/wallet_daemon/tari_permissions.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,7 @@ export class TariPermissionTemplatesRead {
268268
}
269269
}
270270

271-
export type TariPermission = TariPermissionNftGetOwnershipProof | TariPermissionAccountBalance | TariPermissionAccountInfo | TariPermissionAccountList | TariPermissionKeyList | TariPermissionTransactionGet | TariPermissionTransactionSend | TariPermissionGetNft | TariPermissionTransactionsGet | TariPermissionSubstatesRead | TariPermissionTemplatesRead;
271+
export type TariPermission = TariPermissionNftGetOwnershipProof | TariPermissionAccountBalance | TariPermissionAccountInfo | TariPermissionAccountList | TariPermissionKeyList | TariPermissionTransactionGet | TariPermissionTransactionSend | TariPermissionGetNft | TariPermissionTransactionsGet | TariPermissionSubstatesRead | TariPermissionTemplatesRead | string;
272272

273273
export class TariPermissions {
274274
private permissions: TariPermission[];

0 commit comments

Comments
 (0)