wip: working on new connector

main
Steve Korshakov 2022-06-16 09:30:11 +04:00
parent cf0e7baf88
commit f105b2cbc4
5 changed files with 153 additions and 43 deletions

View File

@ -1,4 +1,3 @@
import axios, { AxiosRequestConfig } from "axios";
import { getSecureRandomBytes, keyPairFromSeed } from "ton-crypto";
import { backoff } from "../utils/backoff";
import { toUrlSafe } from "../utils/toURLsafe";
@ -8,7 +7,6 @@ import { Cell, Address, beginCell, CommentMessage, safeSign, contractAddress, sa
import BN from 'bn.js';
import { WalletV4Source } from 'ton-contracts';
import { TonhubHttpTransport } from '../transport/TonhubHttpTransport';
import { TonhubEmbeddedTransport } from '../transport/TonhubEmbeddedTransport';
const sessionStateCodec = t.union([
t.type({
@ -168,15 +166,6 @@ function textToCell(src: string) {
return res;
}
export function autodiscoverTransport() {
if (TonhubEmbeddedTransport.isAvailable()) {
return new TonhubEmbeddedTransport();
}
return new TonhubHttpTransport({
endpoint: 'https://connect.tonhubapi.com'
});
}
export class TonhubConnector {
static extractPublicKey(config: {
@ -277,7 +266,7 @@ export class TonhubConnector {
readonly network: 'mainnet' | 'sandbox';
readonly transport: Transport;
constructor(args?: { network?: 'mainnet' | 'sandbox', transport?: Transport }) {
let network: 'mainnet' | 'sandbox' = 'mainnet';
@ -288,7 +277,7 @@ export class TonhubConnector {
}
this.network = network;
this.transport = args?.transport || autodiscoverTransport();
this.transport = args?.transport || new TonhubHttpTransport();
}
createNewSession = async (args: { name: string, url: string }): Promise<TonhubCreatedSession> => {
@ -306,8 +295,8 @@ export class TonhubConnector {
name: args.name,
url: args.url,
});
if (!session.ok) {
throw Error('Unable to create state');
}
@ -589,7 +578,7 @@ export class TonhubConnector {
return { type: 'expired' };
}
if (res.job !== boc) {
return { type: 'rejected' };
return { type: 'rejected' };
}
if (res.state === 'expired') {
return { type: 'expired' };

View File

@ -0,0 +1,140 @@
import * as t from 'io-ts';
const configCodec = t.type({
version: t.literal(1),
platform: t.union([t.literal('iOS'), t.literal('Android')]),
platformVersion: t.union([t.string, t.number]),
network: t.union([t.literal('sandbox'), t.literal('mainnet')]),
address: t.string,
publicKey: t.string,
walletConfig: t.string,
walletType: t.string,
signature: t.string,
time: t.number,
subkey: t.type({
domain: t.string,
publicKey: t.string,
time: t.number,
signature: t.string
})
});
export type TonhubLocalConfig = {
version: number,
network: 'sandbox' | 'mainnet',
address: string,
publicKey: string,
walletConfig: string,
walletType: string,
signature: string,
time: number,
subkey: {
domain: string,
publicKey: string,
time: number,
signature: string
}
};
export type TonhubLocalTransactionRequest = {
to: string,
value: string,
stateInit?: string | null | undefined,
text?: string | null | undefined,
payload?: string | null | undefined
};
export type TonhubLocalTransactionResponse = {
type: 'success',
response: string
} | {
type: 'rejected'
};
export class TonhubLocalConnector {
static isAvailable() {
if (typeof window === 'undefined') {
return false;
}
if (!((window as any)['ton-x'])) {
return false;
}
let tx = ((window as any)['ton-x']);
if (tx.__IS_TON_X !== true) {
return false;
}
if (!configCodec.is(tx)) {
return false;
}
return true;
}
readonly network: 'mainnet' | 'sandbox';
readonly config: TonhubLocalConfig;
#provider: (name: string, args: any) => Promise<any>
constructor(network: 'mainnet' | 'sandbox') {
if (typeof window === 'undefined') {
throw Error('Not running in browser');
}
if (!((window as any)['ton-x'])) {
throw Error('Not running in dApp browser');
}
let tx = ((window as any)['ton-x']);
if (tx.__IS_TON_X !== true) {
throw Error('Not running in dApp browser');
}
let cfg = tx.config;
if (!configCodec.is(cfg)) {
throw Error('Not running in dApp browser');
}
if (cfg.network !== network) {
throw Error('Invalid network');
}
this.network = network;
this.config = {
version: cfg.version,
network: cfg.network,
address: cfg.address,
publicKey: cfg.publicKey,
walletConfig: cfg.walletConfig,
walletType: cfg.walletType,
signature: cfg.signature,
time: cfg.time,
subkey: {
domain: cfg.subkey.domain,
publicKey: cfg.subkey.publicKey,
time: cfg.subkey.time,
signature: cfg.subkey.signature
}
};
this.#provider = tx.call;
Object.freeze(this.config.subkey);
Object.freeze(this.config);
Object.freeze(this);
}
async requestTransaction(request: TonhubLocalTransactionRequest): Promise<TonhubLocalTransactionResponse> {
let res = await this.#provider('tx', {
network: this.network,
to: request.to,
value: request.value,
stateInit: request.stateInit ? request.stateInit : null,
text: request.text ? request.text : null,
payload: request.payload ? request.payload : null,
});
if (res.type === 'ok') {
let d = res.data;
if (d.state === 'rejected') {
return { type: 'rejected' };
}
if (d.state === 'sent') {
return { type: 'success', response: d.result };
}
throw Error('Unknown reponse');
}
throw Error(res.message);
}
}

View File

@ -12,4 +12,11 @@ export {
TonhubSignRequest,
TonhubSignResponse,
TonhubWalletConfig
} from './connector/TonhubConnector';
} from './connector/TonhubConnector';
export {
TonhubLocalConnector,
TonhubLocalConfig,
TonhubLocalTransactionRequest,
TonhubLocalTransactionResponse
} from './connector/TonhubLocalConnector';

View File

@ -1,25 +0,0 @@
export class TonhubEmbeddedTransport implements Transport {
call<TResult, TArgs>(method: string, args: TArgs): Promise<TResult> {
let tonX = TonhubEmbeddedTransport.get();
if (!tonX) {
throw new Error('ton-x not found');
}
return tonX.call(method, args);
}
private static get() {
if (typeof window === 'undefined' || !(window as any)?.tonX) {
return null;
}
return window && (window as any).tonX as {
call: <TResult, TPayload>(type: string, payload: TPayload) => Promise<TResult>
};
}
static isAvailable() {
return this.get() !== null;
}
}

View File

@ -1,5 +1,4 @@
import axios from 'axios';
import { string } from 'fp-ts';
export class TonhubHttpTransport implements Transport {
private readonly _endpoint: string;