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

Sdk options pattern #4558

Merged
merged 20 commits into from
Jun 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
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
1 change: 1 addition & 0 deletions packages/agents/sdk-wrapper/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
src/sdk-types/
15 changes: 10 additions & 5 deletions packages/agents/sdk-wrapper/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
"license": "MIT",
"scripts": {
"clean": "rimraf ./dist ./tsconfig.tsBuildInfo",
"build": "tsc --build ./tsconfig.build.json",
"copy-sdk-types": "cpx \"../sdk/dist/**/*.d.ts*\" ./src/sdk-types",
"build": "yarn copy-sdk-types && tsc --build ./tsconfig.build.json",
"verify": "yarn test && yarn clean && yarn build && yarn lint --max-warnings 0",
"purge": "yarn clean && rimraf ./node_modules",
"tsp": "yarn run tsp:root \"$@\" --cwd $(pwd)",
Expand All @@ -16,15 +17,19 @@
"types": "dist/index.d.ts",
"files": [
"dist/**/*",
"src/**/*"
"src/**/*",
"types/**/*"
],
"dependencies": {
"@connext/nxtp-txservice": "workspace:*",
"@connext/nxtp-utils": "workspace:*",
"@connext/sdk-core": "workspace:^",
"ethers": "5.7.2"
"ethers": "5.7.2",
"isomorphic-fetch": "3.0.0"
},
"devDependencies": {
"@connext/sdk-core": "workspace:*",
"@types/cpx": "1",
"@types/isomorphic-fetch": "0.0.36",
"cpx": "1.5.0",
"eslint": "8.34.0",
"mocha": "10.2.0",
"nyc": "15.1.0",
Expand Down
183 changes: 183 additions & 0 deletions packages/agents/sdk-wrapper/src/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
///NXTP Config Generator based on vector/modules/router/src/config.ts
import { Type, Static } from "@sinclair/typebox";
import { ajv, ChainData, TAddress, TLogLevel } from "@connext/nxtp-utils";

import { ConnextContractDeployments, ContractPostfix } from "./txservice-types";
import { getChainData } from "./lib/helpers";

export const TAssetDescription = Type.Object({
name: Type.String(),
address: TAddress,
symbol: Type.String(),
mainnetEquivalent: Type.Optional(TAddress),
});

export type AssetDescription = Static<typeof TAssetDescription>;

export const TChainDeployments = Type.Object({
connext: TAddress,
multisend: Type.Optional(TAddress),
unwrapper: Type.Optional(TAddress),
stableSwap: Type.Optional(TAddress),
});

export type ChainDeployments = Static<typeof TChainDeployments>;

export const TChainConfig = Type.Object({
providers: Type.Optional(Type.Array(Type.String())),
gasStations: Type.Optional(Type.Array(Type.String())),
confirmations: Type.Optional(Type.Integer({ minimum: 1 })), // What we consider the "safe confirmations" number for this chain.
chainId: Type.Optional(Type.Number()),
deployments: Type.Optional(TChainDeployments),
assets: Type.Optional(Type.Array(TAssetDescription)), /// Not Being Used
});

export type ChainConfig = Static<typeof TChainConfig>;

export const SdkConfigSchema = Type.Object({
chains: Type.Record(Type.String(), TChainConfig),
signerAddress: Type.Optional(TAddress),
logLevel: Type.Optional(TLogLevel),
cartographerUrl: Type.Optional(Type.String()),
network: Type.Optional(Type.Union([Type.Literal("testnet"), Type.Literal("mainnet"), Type.Literal("local")])),
environment: Type.Optional(Type.Union([Type.Literal("staging"), Type.Literal("production")])),
});

export type SdkConfig = Static<typeof SdkConfigSchema>;

export const TValidationChainConfig = Type.Object({
providers: Type.Array(Type.String()),
gasStations: Type.Array(Type.String()),
confirmations: Type.Integer({ minimum: 1 }), // What we consider the "safe confirmations" number for this chain.
deployments: Type.Object({
connext: TAddress,
multisend: Type.Optional(TAddress),
stableSwap: Type.Optional(TAddress),
}),
assets: Type.Optional(Type.Array(TAssetDescription)), /// Not Being Used
});

export const NxtpValidationSdkConfigSchema = Type.Object({
chains: Type.Record(Type.String(), TValidationChainConfig),
signerAddress: Type.Optional(TAddress),
logLevel: TLogLevel,
cartographerUrl: Type.String(),
network: Type.Union([Type.Literal("testnet"), Type.Literal("mainnet"), Type.Literal("local")]),
environment: Type.Union([Type.Literal("staging"), Type.Literal("production")]),
});

/**
* Gets and validates the router config from the environment.
*
* @returns The router config with sensible defaults
*/
export const getEnvConfig = (
_nxtpConfig: SdkConfig,
chainData: Map<string, ChainData>,
deployments: ConnextContractDeployments,
): SdkConfig => {
const nxtpConfig: SdkConfig = {
..._nxtpConfig,
logLevel: _nxtpConfig.logLevel || "info",
network: _nxtpConfig.network || "mainnet",
environment: _nxtpConfig.environment || "production",
cartographerUrl: _nxtpConfig.cartographerUrl
? _nxtpConfig.cartographerUrl
: _nxtpConfig.network === "testnet"
? _nxtpConfig.environment === "staging"
? "https://postgrest.testnet.staging.connext.ninja"
: "https://postgrest.testnet.connext.ninja"
: "https://postgrest.mainnet.connext.ninja",
};

const defaultConfirmations = chainData && (chainData.get("1")?.confirmations ?? 1 + 3);

const contractPostfix: ContractPostfix =
nxtpConfig.environment === "production"
? ""
: (`${nxtpConfig.environment![0].toUpperCase()}${nxtpConfig.environment!.slice(1)}` as ContractPostfix);
// add contract deployments if they exist
Object.entries(nxtpConfig.chains).forEach(([domainId, chainConfig]) => {
const chainDataForChain = chainData.get(domainId);
const chainRecommendedConfirmations = chainDataForChain?.confirmations ?? defaultConfirmations;
const chainRecommendedGasStations = chainDataForChain?.gasStations ?? [];

// Make sure deployments is filled out correctly.
// allow passed in address to override
// format: { [domainId]: { { "deployments": { "connext": <address>, ... } }
nxtpConfig.chains[domainId].deployments = {
connext:
chainConfig.deployments?.connext ??
(() => {
if (chainDataForChain) {
const res = deployments.connext(chainDataForChain.chainId, contractPostfix);
if (res) {
return res.address;
}
}
throw new Error(`No Connext contract address for domain ${domainId}`);
})(),
multisend:
chainConfig.deployments?.multisend ??
(() => {
if (chainDataForChain) {
const res = deployments.multisend(chainDataForChain.chainId);
return res?.address;
}
return undefined;
})(),
unwrapper:
chainConfig.deployments?.unwrapper ??
(() => {
if (chainDataForChain) {
const res = deployments.unwrapper(chainDataForChain.chainId);
return res?.address;
}
return undefined;
})(),
};

nxtpConfig.chains[domainId].confirmations = chainConfig.confirmations ?? chainRecommendedConfirmations;

nxtpConfig.chains[domainId].gasStations = (nxtpConfig.chains[domainId].gasStations ?? []).concat(
chainRecommendedGasStations,
);
});

const validate = ajv.compile(NxtpValidationSdkConfigSchema);

const valid = validate(nxtpConfig);

if (!valid) {
throw new Error(validate.errors?.map((err: unknown) => JSON.stringify(err, null, 2)).join(","));
}

return nxtpConfig;
};

/**
* Caches and returns the environment config
*
* @returns The config
*/
export const getConfig = async (
_nxtpConfig: SdkConfig,
deployments: ConnextContractDeployments,
_chainData?: Map<string, ChainData>,
): Promise<{ nxtpConfig: SdkConfig; chainData: Map<string, ChainData> }> => {
let chainData = _chainData;
if (!chainData) {
chainData = await getChainData();
}
const nxtpConfig = getEnvConfig(_nxtpConfig, chainData, deployments);
return { nxtpConfig: nxtpConfig, chainData: chainData };
};

export const domainsToChainNames: Record<string, string> = {
"6648936": "ethereum",
"1869640809": "optimism",
"1886350457": "polygon",
"1634886255": "arbitrum",
"6450786": "bsc",
"6778479": "xdai",
};
5 changes: 2 additions & 3 deletions packages/agents/sdk-wrapper/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { SdkConfig, SdkConfigSchema } from "@connext/sdk-core";

export { SdkShared } from "./sdkShared";
export { SdkBase } from "./sdkBase";
export { SdkRouter } from "./sdkRouter";
export { SdkPool } from "./sdkPool";
export { SdkUtils } from "./sdkUtils";
export { SdkConfig, SdkConfigSchema };
export { SdkConfig } from "./config";
export { create } from "./sdk";
2 changes: 1 addition & 1 deletion packages/agents/sdk-wrapper/src/lib/helpers/shared.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { getContractInterfaces } from "@connext/nxtp-txservice";
import {
ajv,
TUrl,
Expand All @@ -11,6 +10,7 @@ import {
getHardcodedGasLimits as _getHardcodedGasLimits,
calculateRelayerFee as _calculateRelayerFee,
} from "@connext/nxtp-utils";
import { getContractInterfaces } from "../../txservice-types";
import { axiosGet } from "../../mockable";
import { providers } from "ethers";

Expand Down
2 changes: 1 addition & 1 deletion packages/agents/sdk-wrapper/src/sdk.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Logger, ChainData } from "@connext/nxtp-utils";
import { SdkConfig } from "@connext/sdk-core/src/config";

import type { SdkConfig } from "./sdk-types";
import { SdkUtils } from "./sdkUtils";
import { SdkBase } from "./sdkBase";
import { SdkRouter } from "./sdkRouter";
Expand Down
27 changes: 21 additions & 6 deletions packages/agents/sdk-wrapper/src/sdkBase.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { Logger, createLoggingContext, ChainData } from "@connext/nxtp-utils";
import { providers, BigNumber, BigNumberish } from "ethers";
import {

import type {
SdkConfig,
SdkXCallParams,
SdkBumpTransferParams,
SdkUpdateSlippageParams,
SdkEstimateRelayerFeeParams,
} from "@connext/sdk-core";

} from "./sdk-types";
import { axiosPost } from "./mockable";
import { SdkShared } from "./sdkShared";

Expand All @@ -28,23 +28,38 @@ export class SdkBase extends SdkShared {
const { requestContext, methodContext } = createLoggingContext(this.xcall.name);
this.logger.info("Method start", requestContext, methodContext, { params });

const response = await axiosPost(`${this.baseUri}/xcall`, params);
const _options = params.options ?? {
chains: this.config.chains,
signerAddress: this.config.signerAddress,
};

const response = await axiosPost(`${this.baseUri}/xcall`, { ...params, options: _options });
return response.data;
}

async updateSlippage(params: SdkUpdateSlippageParams): Promise<providers.TransactionRequest> {
const { requestContext, methodContext } = createLoggingContext(this.updateSlippage.name);
this.logger.info("Method start", requestContext, methodContext, { params });

const response = await axiosPost(`${this.baseUri}/updateSlippage`, params);
const _options = params.options ?? {
chains: this.config.chains,
signerAddress: this.config.signerAddress,
};

const response = await axiosPost(`${this.baseUri}/updateSlippage`, { ...params, options: _options });
return response.data;
}

async bumpTransfer(params: SdkBumpTransferParams): Promise<providers.TransactionRequest> {
const { requestContext, methodContext } = createLoggingContext(this.bumpTransfer.name);
this.logger.info("Method start", requestContext, methodContext, { params });

const response = await axiosPost(`${this.baseUri}/bumpTransfer`, params);
const _options = params.options ?? {
chains: this.config.chains,
signerAddress: this.config.signerAddress,
};

const response = await axiosPost(`${this.baseUri}/bumpTransfer`, { ...params, options: _options });
return response.data;
}

Expand Down
Loading