Skip to content

Commit

Permalink
Remove @coinbase/wallet-sdk dependency (#290)
Browse files Browse the repository at this point in the history
* Revert "update @coinbase/wallet-sdk version (#289)"

This reverts commit a084335.

* remove dependency

* fix dependency
  • Loading branch information
bangtoven committed Jan 19, 2024
1 parent 9655162 commit 80ad0a1
Show file tree
Hide file tree
Showing 7 changed files with 322 additions and 334 deletions.
4 changes: 2 additions & 2 deletions react-native/client/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@coinbase/wallet-mobile-sdk",
"version": "1.0.11",
"version": "1.0.12",
"description": "Coinbase Wallet Mobile SDK for React Native",
"main": "build/CoinbaseWalletSDK.js",
"types": "build/CoinbaseWalletSDK.d.ts",
Expand All @@ -27,11 +27,11 @@
"license": "Apache-2.0",
"homepage": "https://github.com/coinbase/wallet-mobile-sdk#readme",
"dependencies": {
"@coinbase/wallet-sdk": "3.9.1",
"@metamask/safe-event-emitter": "2.0.0",
"eth-rpc-errors": "4.0.3",
"buffer": "6.0.3",
"bn.js": "5.2.1",
"events": "^3.0.0",
"react-native-mmkv": "2.11.0"
},
"devDependencies": {
Expand Down
22 changes: 17 additions & 5 deletions react-native/client/src/WalletMobileSDKEVMProvider.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import {
RequestArguments,
Web3Provider,
} from "@coinbase/wallet-sdk/dist/provider/Web3Provider";
} from "./types/provider/Web3Provider";
import {
JSONRPCRequest,
JSONRPCResponse,
} from "@coinbase/wallet-sdk/dist/provider/JSONRPC";
} from "./types/provider/JSONRPC";
import {
AddressString,
Callback,
IntNumber,
} from "@coinbase/wallet-sdk/dist/core/type";
} from "./types/core/type";
import { ethErrors } from "eth-rpc-errors";
import {
initiateHandshake,
Expand All @@ -29,8 +29,7 @@ import {
hexStringFromBuffer,
hexStringFromIntNumber,
prepend0x,
} from "@coinbase/wallet-sdk/dist/core/util";
import { EthereumTransactionParams } from "@coinbase/wallet-sdk/dist/relay/walletlink/type/EthereumTransactionParams";
} from "./types/core/util";
import BN from "bn.js";
import { MMKV, NativeMMKV } from "react-native-mmkv";
import SafeEventEmitter from "@metamask/safe-event-emitter";
Expand Down Expand Up @@ -77,6 +76,19 @@ interface WatchAssetParams {
};
}

interface EthereumTransactionParams {
fromAddress: AddressString;
toAddress: AddressString | null;
weiValue: BN;
data: Buffer;
nonce: IntNumber | null;
gasPriceInWei: BN | null;
maxFeePerGas: BN | null; // in wei
maxPriorityFeePerGas: BN | null; // in wei
gasLimit: BN | null;
chainId: IntNumber;
}

export class WalletMobileSDKEVMProvider
extends SafeEventEmitter
implements Web3Provider
Expand Down
38 changes: 38 additions & 0 deletions react-native/client/src/types/core/type.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Copyright (c) 2018-2023 Coinbase, Inc. <https://www.coinbase.com/>
// Licensed under the Apache License, version 2.0

interface Tag<T extends string, RealType> {
__tag__: T;
__realType__: RealType;
}

export type OpaqueType<T extends string, U> = U & Tag<T, U>;

export function OpaqueType<T extends Tag<string, unknown>>() {
return (value: T extends Tag<string, infer U> ? U : never): T => value as T;
}

export type HexString = OpaqueType<'HexString', string>;
export const HexString = OpaqueType<HexString>();

export type AddressString = OpaqueType<'AddressString', string>;
export const AddressString = OpaqueType<AddressString>();

export type BigIntString = OpaqueType<'BigIntString', string>;
export const BigIntString = OpaqueType<BigIntString>();

export type IntNumber = OpaqueType<'IntNumber', number>;
export function IntNumber(num: number): IntNumber {
return Math.floor(num) as IntNumber;
}

export type RegExpString = OpaqueType<'RegExpString', string>;
export const RegExpString = OpaqueType<RegExpString>();

export type Callback<T> = (err: Error | null, result: T | null) => void;

export enum ProviderType {
CoinbaseWallet = 'CoinbaseWallet',
MetaMask = 'MetaMask',
Unselected = '',
}
165 changes: 165 additions & 0 deletions react-native/client/src/types/core/util.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
// Copyright (c) 2018-2023 Coinbase, Inc. <https://www.coinbase.com/>
// Licensed under the Apache License, version 2.0

import BN from 'bn.js';

import { AddressString, BigIntString, HexString, IntNumber, RegExpString } from './type';

const INT_STRING_REGEX = /^[0-9]*$/;
const HEXADECIMAL_STRING_REGEX = /^[a-f0-9]*$/;

export function hexStringToUint8Array(hexString: string): Uint8Array {
return new Uint8Array(hexString.match(/.{1,2}/g)!.map((byte) => parseInt(byte, 16)));
}

export function hexStringFromBuffer(buf: Buffer, includePrefix = false): HexString {
const hex = buf.toString('hex');
return HexString(includePrefix ? `0x${hex}` : hex);
}

export function bigIntStringFromBN(bn: BN): BigIntString {
return BigIntString(bn.toString(10));
}

export function intNumberFromHexString(hex: HexString): IntNumber {
return IntNumber(new BN(ensureEvenLengthHexString(hex, false), 16).toNumber());
}

export function hexStringFromIntNumber(num: IntNumber): HexString {
return HexString(`0x${new BN(num).toString(16)}`);
}

export function has0xPrefix(str: string): boolean {
return str.startsWith('0x') || str.startsWith('0X');
}

export function strip0x(hex: string): string {
if (has0xPrefix(hex)) {
return hex.slice(2);
}
return hex;
}

export function prepend0x(hex: string): string {
if (has0xPrefix(hex)) {
return `0x${hex.slice(2)}`;
}
return `0x${hex}`;
}

export function isHexString(hex: unknown): hex is HexString {
if (typeof hex !== 'string') {
return false;
}
const s = strip0x(hex).toLowerCase();
return HEXADECIMAL_STRING_REGEX.test(s);
}

class InvalidParamsError extends Error {
code = -32602;
constructor(message: string) {
super(message);
}
}

export function ensureHexString(hex: unknown, includePrefix = false): HexString {
if (typeof hex === 'string') {
const s = strip0x(hex).toLowerCase();
if (HEXADECIMAL_STRING_REGEX.test(s)) {
return HexString(includePrefix ? `0x${s}` : s);
}
}
throw new InvalidParamsError(`"${String(hex)}" is not a hexadecimal string`);
}

export function ensureEvenLengthHexString(hex: unknown, includePrefix = false): HexString {
let h = ensureHexString(hex, false);
if (h.length % 2 === 1) {
h = HexString(`0${h}`);
}
return includePrefix ? HexString(`0x${h}`) : h;
}

export function ensureAddressString(str: unknown): AddressString {
if (typeof str === 'string') {
const s = strip0x(str).toLowerCase();
if (isHexString(s) && s.length === 40) {
return AddressString(prepend0x(s));
}
}
throw new InvalidParamsError(`Invalid Ethereum address: ${String(str)}`);
}

export function ensureBuffer(str: unknown): Buffer {
if (Buffer.isBuffer(str)) {
return str;
}
if (typeof str === 'string') {
if (isHexString(str)) {
const s = ensureEvenLengthHexString(str, false);
return Buffer.from(s, 'hex');
}
return Buffer.from(str, 'utf8');
}
throw new InvalidParamsError(`Not binary data: ${String(str)}`);
}

export function ensureIntNumber(num: unknown): IntNumber {
if (typeof num === 'number' && Number.isInteger(num)) {
return IntNumber(num);
}
if (typeof num === 'string') {
if (INT_STRING_REGEX.test(num)) {
return IntNumber(Number(num));
}
if (isHexString(num)) {
return IntNumber(new BN(ensureEvenLengthHexString(num, false), 16).toNumber());
}
}
throw new InvalidParamsError(`Not an integer: ${String(num)}`);
}

export function ensureRegExpString(regExp: unknown): RegExpString {
if (regExp instanceof RegExp) {
return RegExpString(regExp.toString());
}
throw new InvalidParamsError(`Not a RegExp: ${String(regExp)}`);
}

export function ensureBN(val: unknown): BN {
if (val !== null && (BN.isBN(val) || isBigNumber(val))) {
return new BN((val as any).toString(10), 10);
}
if (typeof val === 'number') {
return new BN(ensureIntNumber(val));
}
if (typeof val === 'string') {
if (INT_STRING_REGEX.test(val)) {
return new BN(val, 10);
}
if (isHexString(val)) {
return new BN(ensureEvenLengthHexString(val, false), 16);
}
}
throw new InvalidParamsError(`Not an integer: ${String(val)}`);
}

export function ensureParsedJSONObject<T extends object>(val: unknown): T {
if (typeof val === 'string') {
return JSON.parse(val) as T;
}

if (typeof val === 'object') {
return val as T;
}

throw new InvalidParamsError(`Not a JSON string or an object: ${String(val)}`);
}

export function isBigNumber(val: unknown): boolean {
if (val == null || typeof (val as any).constructor !== 'function') {
return false;
}
const { constructor } = val as any;
return typeof constructor.config === 'function' && typeof constructor.EUCLID === 'number';
}
58 changes: 58 additions & 0 deletions react-native/client/src/types/provider/JSONRPC.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// Copyright (c) 2018-2023 Coinbase, Inc. <https://www.coinbase.com/>
// Licensed under the Apache License, version 2.0

export type JSONRPCMethod =
// synchronous or asynchronous
| 'eth_accounts'
| 'eth_coinbase'
| 'net_version'
| 'eth_chainId'
| 'eth_uninstallFilter' // synchronous

// asynchronous only
| 'eth_requestAccounts'
| 'eth_sign'
| 'eth_ecRecover'
| 'personal_sign'
| 'personal_ecRecover'
| 'eth_signTransaction'
| 'eth_sendRawTransaction'
| 'eth_sendTransaction'
| 'eth_signTypedData_v1'
| 'eth_signTypedData_v2'
| 'eth_signTypedData_v3'
| 'eth_signTypedData_v4'
| 'eth_signTypedData'
| 'walletlink_arbitrary' // compatibility
| 'wallet_addEthereumChain'
| 'wallet_switchEthereumChain'
| 'wallet_watchAsset'

// asynchronous pub/sub
| 'eth_subscribe'
| 'eth_unsubscribe'

// asynchronous filter methods
| 'eth_newFilter'
| 'eth_newBlockFilter'
| 'eth_newPendingTransactionFilter'
| 'eth_getFilterChanges'
| 'eth_getFilterLogs';

export interface JSONRPCRequest<T = any> {
jsonrpc: '2.0';
id: number;
method: string;
params: T;
}

export interface JSONRPCResponse<T = any, U = any> {
jsonrpc: '2.0';
id: number;
result?: T;
error?: {
code: number;
message: string;
data?: U;
} | null;
}
32 changes: 32 additions & 0 deletions react-native/client/src/types/provider/Web3Provider.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Copyright (c) 2018-2023 Coinbase, Inc. <https://www.coinbase.com/>
// Licensed under the Apache License, version 2.0

import { Callback } from '../core/type';
import { JSONRPCRequest, JSONRPCResponse } from './JSONRPC';

export interface Web3Provider {
send(request: JSONRPCRequest): JSONRPCResponse;
send(request: JSONRPCRequest[]): JSONRPCResponse[];
send(request: JSONRPCRequest, callback: Callback<JSONRPCResponse>): void;
send(request: JSONRPCRequest[], callback: Callback<JSONRPCResponse[]>): void;
send<T = unknown>(method: string, params?: unknown[] | unknown): Promise<T>;

sendAsync(request: JSONRPCRequest, callback: Callback<JSONRPCResponse>): void;
sendAsync(request: JSONRPCRequest[], callback: Callback<JSONRPCResponse[]>): void;

request<T>(args: RequestArguments): Promise<T>;

host: string;
connected: boolean;
chainId: string;
supportsSubscriptions(): boolean;
disconnect(): boolean;
}

export interface RequestArguments {
/** The RPC method to request. */
method: string;

/** The params of the RPC method, if any. */
params?: unknown;
}
Loading

0 comments on commit 80ad0a1

Please sign in to comment.