Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ts-sdk] generate TS type guards (replace superstruct) #1509

Merged
merged 17 commits into from
Apr 21, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
[ts-sdk] Implement getOwnedObjects
  • Loading branch information
666lcz committed Apr 20, 2022
commit 9c5af2e9136bdfce6cab24cee80ec299675876cd
2 changes: 2 additions & 0 deletions sdk/typescript/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@
"dependencies": {
"bn.js": "^5.2.0",
"buffer": "^6.0.3",
"jayson": "^3.6.6",
"superstruct": "^0.15.4",
"tweetnacl": "^1.0.3",
"util": "^0.12.4"
},
Expand Down
23 changes: 17 additions & 6 deletions sdk/typescript/src/providers/json-rpc-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@ import {
SignedTransaction,
TransactionResponse,
} from './provider';
import { JsonRpcClient } from '../rpc/client';
import { array, type as pick } from 'superstruct';

export class JsonRpcProvider extends Provider {
//@ts-ignore
private endpointURL: string;
private client: JsonRpcClient;

/**
* Establish a connection to a Sui Gateway endpoint
Expand All @@ -19,13 +20,23 @@ export class JsonRpcProvider extends Provider {
*/
constructor(endpoint: string) {
super();
this.endpointURL = endpoint;
this.client = new JsonRpcClient(endpoint);
}

// Objects
async getObjectRefs(_address: string): Promise<ObjectRef[]> {
// TODO: implement the function with a RPC client
return [];
async getOwnedObjectRefs(address: string): Promise<ObjectRef[]> {
try {
const resp = await this.client.requestWithType(
'sui_getOwnedObjects',
[address],
pick({ objects: array(ObjectRef) })
);
return resp.objects;
} catch (err) {
throw new Error(
`Error fetching owned object refs: ${err} for address ${address}`
);
}
}

// Transactions
Expand Down
16 changes: 10 additions & 6 deletions sdk/typescript/src/providers/provider.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
// Copyright (c) 2022, Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

import { type as pick, string, Infer, number } from 'superstruct';

///////////////////////////////
// Exported Types
export interface ObjectRef {
objectDigest: string;
objectId: string;
version: string;
}
export type ObjectRef = Infer<typeof ObjectRef>;

export interface SignedTransaction {
txBytes: string;
Expand All @@ -22,7 +20,7 @@ export type TransactionResponse = string;
// Exported Abstracts
export abstract class Provider {
// Objects
abstract getObjectRefs(address: string): Promise<ObjectRef[]>;
abstract getOwnedObjectRefs(address: string): Promise<ObjectRef[]>;

// Transactions
abstract executeTransaction(
Expand All @@ -31,3 +29,9 @@ export abstract class Provider {

// TODO: add more interface methods
}

export const ObjectRef = pick({
digest: string(),
objectId: string(),
version: number(),
});
4 changes: 2 additions & 2 deletions sdk/typescript/src/providers/void-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ import {

export class VoidProvider extends Provider {
// Objects
async getObjectRefs(_address: string): Promise<ObjectRef[]> {
throw this.newError('getObjectRefs');
async getOwnedObjectRefs(_address: string): Promise<ObjectRef[]> {
throw this.newError('getOwnedObjectRefs');
}

// Transactions
Expand Down
100 changes: 100 additions & 0 deletions sdk/typescript/src/rpc/client.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
// Copyright (c) 2022, Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

import RpcClient from 'jayson/lib/client/browser';
import {
literal,
type as pick,
string,
Struct,
unknown,
assert,
optional,
any,
is,
} from 'superstruct';

/**
* An object defining headers to be passed to the RPC server
*/
export type HttpHeaders = { [header: string]: string };

export class JsonRpcClient {
private rpcClient: RpcClient;

constructor(url: string, httpHeaders?: HttpHeaders) {
this.rpcClient = this.createRpcClient(url, httpHeaders);
}

private createRpcClient(url: string, httpHeaders?: HttpHeaders): RpcClient {
const client = new RpcClient(async (request, callback) => {
const options = {
method: 'POST',
body: request,
headers: Object.assign(
{
'Content-Type': 'application/json',
},
httpHeaders || {}
),
};

try {
let res: Response = await fetch(url, options);
const text = await res.text();
if (res.ok) {
callback(null, text);
} else {
callback(new Error(`${res.status} ${res.statusText}: ${text}`));
}
} catch (err) {
if (err instanceof Error) callback(err);
}
}, {});

return client;
}

async requestWithType<T, S>(
method: string,
args: Array<any>,
schema: Struct<T, S>
): Promise<T> {
const response = await this.request(method, args);
if (is(response, ErrorResponse)) {
throw new Error(`RPC Error: ${response.error.message}`);
} else if (is(response, ValidResponse)) {
assert(response.result, schema);
return response.result;
}
throw new Error(`Unexpected RPC Response: ${response}`);
}

async request(method: string, args: Array<any>): Promise<any> {
return new Promise((resolve, reject) => {
this.rpcClient.request(method, args, (err: any, response: any) => {
if (err) {
reject(err);
return;
}
resolve(response);
});
});
}
}

const ValidResponse = pick({
jsonrpc: literal('2.0'),
id: string(),
result: unknown(),
});

const ErrorResponse = pick({
jsonrpc: literal('2.0'),
id: string(),
error: pick({
code: unknown(),
message: string(),
data: optional(any()),
}),
});
Loading