@ember-finance/sdk 2.10.4 → 2.11.0-pre.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/api/v2/apis/vaults-api.d.ts +42 -0
- package/dist/src/api/v2/apis/vaults-api.js +87 -0
- package/dist/src/api/v2/models/chain.d.ts +6 -0
- package/dist/src/api/v2/models/coin-placement.d.ts +95 -0
- package/dist/src/api/v2/models/coin-placement.js +17 -0
- package/dist/src/api/v2/models/coin-placements-response.d.ts +25 -0
- package/dist/src/api/v2/models/coin-placements-response.js +14 -0
- package/dist/src/api/v2/models/index.d.ts +3 -0
- package/dist/src/api/v2/models/index.js +3 -0
- package/dist/src/api/v2/models/instant-withdraw-config.d.ts +21 -2
- package/dist/src/api/v2/models/poc-report-protocol-asset.d.ts +60 -0
- package/dist/src/api/v2/models/poc-report-protocol-asset.js +18 -0
- package/dist/src/api/v2/models/poc-report-protocol.d.ts +13 -0
- package/dist/src/api/v2/models/transparency-row.d.ts +1 -1
- package/dist/src/placements/adapters/alphalend.d.ts +1 -0
- package/dist/src/placements/adapters/alphalend.js +58 -0
- package/dist/src/placements/adapters/bluefin-spot.d.ts +1 -0
- package/dist/src/placements/adapters/bluefin-spot.js +78 -0
- package/dist/src/placements/adapters/current.d.ts +1 -0
- package/dist/src/placements/adapters/current.js +70 -0
- package/dist/src/placements/adapters/evm-protocols.d.ts +2 -0
- package/dist/src/placements/adapters/evm-protocols.js +15 -0
- package/dist/src/placements/adapters/factory.d.ts +15 -0
- package/dist/src/placements/adapters/factory.js +62 -0
- package/dist/src/placements/adapters/index.d.ts +13 -0
- package/dist/src/placements/adapters/index.js +23 -0
- package/dist/src/placements/adapters/navi.d.ts +1 -0
- package/dist/src/placements/adapters/navi.js +53 -0
- package/dist/src/placements/adapters/pendle.d.ts +9 -0
- package/dist/src/placements/adapters/pendle.js +108 -0
- package/dist/src/placements/adapters/suilend.d.ts +1 -0
- package/dist/src/placements/adapters/suilend.js +57 -0
- package/dist/src/placements/client.d.ts +16 -0
- package/dist/src/placements/client.js +157 -0
- package/dist/src/placements/evm.d.ts +11 -0
- package/dist/src/placements/evm.js +48 -0
- package/dist/src/placements/index.d.ts +8 -0
- package/dist/src/placements/index.js +8 -0
- package/dist/src/placements/pointers.d.ts +24 -0
- package/dist/src/placements/pointers.js +125 -0
- package/dist/src/placements/registry.d.ts +11 -0
- package/dist/src/placements/registry.js +19 -0
- package/dist/src/placements/sui.d.ts +35 -0
- package/dist/src/placements/sui.js +189 -0
- package/dist/src/placements/types.d.ts +139 -0
- package/dist/src/placements/types.js +1 -0
- package/dist/src/placements/vaults.d.ts +15 -0
- package/dist/src/placements/vaults.js +97 -0
- package/package.json +6 -1
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { ChainType } from "../common/constants.js";
|
|
2
|
+
/** Identifier for a protocol adapter, e.g. "bluefin-spot". */
|
|
3
|
+
export type ProtocolId = string;
|
|
4
|
+
export interface ChainRef {
|
|
5
|
+
type: ChainType;
|
|
6
|
+
/** EVM network id. Absent on chains that have none. */
|
|
7
|
+
chainId?: number;
|
|
8
|
+
/** Chain identifier, e.g. "sui-mainnet". */
|
|
9
|
+
identifier?: string;
|
|
10
|
+
}
|
|
11
|
+
/** An Ember vault receipt coin, as listed by the vaults API. */
|
|
12
|
+
export interface ReceiptCoin {
|
|
13
|
+
/** Sui coin type, or EVM token address. */
|
|
14
|
+
coin: string;
|
|
15
|
+
chain: ChainRef;
|
|
16
|
+
decimals: number;
|
|
17
|
+
symbol?: string;
|
|
18
|
+
/** Display name of the vault this coin belongs to. */
|
|
19
|
+
vault?: string;
|
|
20
|
+
/** RPC endpoint for this coin's chain, when one is published. */
|
|
21
|
+
rpcUrl?: string;
|
|
22
|
+
}
|
|
23
|
+
export type PointerOrigin = "Registry" | "Manual";
|
|
24
|
+
/** Somewhere a receipt coin is listed. Carries no amount. */
|
|
25
|
+
export interface PlacementRef {
|
|
26
|
+
protocol: ProtocolId;
|
|
27
|
+
chain: ChainRef;
|
|
28
|
+
/** Pool, market or vault address. */
|
|
29
|
+
venue: string;
|
|
30
|
+
coin: string;
|
|
31
|
+
/** Decimals of `coin`. */
|
|
32
|
+
decimals: number;
|
|
33
|
+
/**
|
|
34
|
+
* The protocol's display name, e.g. "Current Finance". Absent when the
|
|
35
|
+
* vaults API has no catalogue entry — render `protocol` then.
|
|
36
|
+
*/
|
|
37
|
+
protocolName?: string;
|
|
38
|
+
/** Icon for the protocol, when one is catalogued. */
|
|
39
|
+
protocolLogoUrl?: string;
|
|
40
|
+
source: PointerOrigin;
|
|
41
|
+
/** Human-readable venue name, for display only. */
|
|
42
|
+
label?: string;
|
|
43
|
+
/**
|
|
44
|
+
* The token an account holds for its position here, when that is not the
|
|
45
|
+
* venue itself. Defaults to `venue`.
|
|
46
|
+
*/
|
|
47
|
+
shareToken?: string;
|
|
48
|
+
/** Deep link to the venue, for the caller to render. */
|
|
49
|
+
url?: string;
|
|
50
|
+
/**
|
|
51
|
+
* RPC endpoint for this chain, when one is published. Absent means fall
|
|
52
|
+
* back to whatever the reader was configured with.
|
|
53
|
+
*/
|
|
54
|
+
rpcUrl?: string;
|
|
55
|
+
}
|
|
56
|
+
/** A resolved pointer: what one account holds there. */
|
|
57
|
+
export interface Placement extends PlacementRef {
|
|
58
|
+
/** The account's own position, in base units of `coin`. */
|
|
59
|
+
amount: string;
|
|
60
|
+
readAt: string;
|
|
61
|
+
}
|
|
62
|
+
export interface PlacementFailure {
|
|
63
|
+
protocol: ProtocolId;
|
|
64
|
+
stage: "discover" | "read";
|
|
65
|
+
coin?: string;
|
|
66
|
+
reason: string;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* One vault's shares for one account.
|
|
70
|
+
*
|
|
71
|
+
* A non-empty `failures` means `placements` is incomplete — a caller showing a
|
|
72
|
+
* total should say so rather than quietly under-report.
|
|
73
|
+
*/
|
|
74
|
+
export interface AccountShares {
|
|
75
|
+
vaultId: string;
|
|
76
|
+
coin: ReceiptCoin;
|
|
77
|
+
/** Held in the account's own wallet. Base units of `coin`. */
|
|
78
|
+
available: string;
|
|
79
|
+
/** Wrapped into a cover vault. Absent when the vault is not covered. */
|
|
80
|
+
covered?: string;
|
|
81
|
+
placements: Placement[];
|
|
82
|
+
failures: PlacementFailure[];
|
|
83
|
+
}
|
|
84
|
+
export interface SuiObjectContents {
|
|
85
|
+
address: string;
|
|
86
|
+
type: string;
|
|
87
|
+
json: Record<string, unknown>;
|
|
88
|
+
}
|
|
89
|
+
export interface SuiDynamicField {
|
|
90
|
+
name: unknown;
|
|
91
|
+
valueType: string;
|
|
92
|
+
value: unknown;
|
|
93
|
+
}
|
|
94
|
+
/** Narrow read port over Sui, so a caller can supply its own transport. */
|
|
95
|
+
export interface SuiReader {
|
|
96
|
+
objects(ids: string[]): Promise<Record<string, SuiObjectContents>>;
|
|
97
|
+
dynamicFields(parentId: string, limit?: number): Promise<SuiDynamicField[]>;
|
|
98
|
+
/**
|
|
99
|
+
* One dynamic field addressed by its BCS-encoded key. Resolves to undefined
|
|
100
|
+
* when the key is absent.
|
|
101
|
+
*/
|
|
102
|
+
dynamicField(parentId: string, key: {
|
|
103
|
+
type: string;
|
|
104
|
+
bcs: string;
|
|
105
|
+
}): Promise<unknown | undefined>;
|
|
106
|
+
/** Total balance an address holds of one coin type, in base units. */
|
|
107
|
+
balance(owner: string, coinType: string): Promise<string>;
|
|
108
|
+
/** Objects of one type owned by an address. */
|
|
109
|
+
ownedObjects(owner: string, type: string): Promise<SuiObjectContents[]>;
|
|
110
|
+
}
|
|
111
|
+
/** Narrow read port over EVM: one `eth_call` is all these reads need. */
|
|
112
|
+
export interface EvmReader {
|
|
113
|
+
/** `endpoint`, when given, overrides whatever the reader is configured with. */
|
|
114
|
+
call(chainId: number, to: string, data: string, endpoint?: string): Promise<string>;
|
|
115
|
+
}
|
|
116
|
+
/** Where pointers come from. */
|
|
117
|
+
export interface PointerSource {
|
|
118
|
+
placements(protocol: ProtocolId, coin: ReceiptCoin): Promise<PlacementRef[]>;
|
|
119
|
+
}
|
|
120
|
+
/** Resolves a vault to the receipt coins it issues, one per chain it runs on. */
|
|
121
|
+
export interface VaultCoinsResolver {
|
|
122
|
+
coinsForVault(vaultId: string): Promise<ReceiptCoin[]>;
|
|
123
|
+
coverVault?(coin: ReceiptCoin): Promise<string | undefined>;
|
|
124
|
+
}
|
|
125
|
+
export interface PlacementsContext {
|
|
126
|
+
sui?: SuiReader;
|
|
127
|
+
evm?: EvmReader;
|
|
128
|
+
pointers: PointerSource;
|
|
129
|
+
vaults?: VaultCoinsResolver;
|
|
130
|
+
}
|
|
131
|
+
/** The extension seam. One protocol, registered with `registerAdapter`. */
|
|
132
|
+
export interface ProtocolAdapter {
|
|
133
|
+
readonly id: ProtocolId;
|
|
134
|
+
readonly chain: ChainType;
|
|
135
|
+
/** Pointers only, carrying no amounts. */
|
|
136
|
+
discover(coin: ReceiptCoin, ctx: PlacementsContext): Promise<PlacementRef[]>;
|
|
137
|
+
/** What `account` holds at each venue, in base units of `ref.coin`. */
|
|
138
|
+
read(refs: PlacementRef[], account: string, ctx: PlacementsContext): Promise<Placement[]>;
|
|
139
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { PlatformEnv } from "../common/constants.js";
|
|
2
|
+
import { VaultCoinsResolver } from "./types.js";
|
|
3
|
+
export interface HttpVaultCoinsOptions {
|
|
4
|
+
/** Vaults API environment. Defaults to prod. */
|
|
5
|
+
env?: PlatformEnv;
|
|
6
|
+
/** Overrides `env` entirely. For a local deployment, or a proxy. */
|
|
7
|
+
baseUrl?: string;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Resolves a vault to the receipt coins it issues, from the vaults API.
|
|
11
|
+
*
|
|
12
|
+
* A vault runs on one or more chains and issues a distinct receipt coin on
|
|
13
|
+
* each, so this returns one entry per chain rather than assuming a single coin.
|
|
14
|
+
*/
|
|
15
|
+
export declare function httpVaultCoinsResolver(options?: HttpVaultCoinsOptions): VaultCoinsResolver;
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { environmentConfig } from "../common/constants.js";
|
|
2
|
+
/**
|
|
3
|
+
* Resolves a vault to the receipt coins it issues, from the vaults API.
|
|
4
|
+
*
|
|
5
|
+
* A vault runs on one or more chains and issues a distinct receipt coin on
|
|
6
|
+
* each, so this returns one entry per chain rather than assuming a single coin.
|
|
7
|
+
*/
|
|
8
|
+
export function httpVaultCoinsResolver(options = {}) {
|
|
9
|
+
const baseUrl = (options.baseUrl ?? environmentConfig[options.env ?? "prod"].apiHost).replace(/\/$/, "");
|
|
10
|
+
const get = async (path) => {
|
|
11
|
+
const response = await fetch(`${baseUrl}${path}`, {
|
|
12
|
+
headers: { Accept: "application/json" }
|
|
13
|
+
});
|
|
14
|
+
if (!response.ok)
|
|
15
|
+
throw new Error(`vaults api ${response.status} for ${path}`);
|
|
16
|
+
return (await response.json());
|
|
17
|
+
};
|
|
18
|
+
// The chain catalogue is what carries the EVM network id. Without it an EVM
|
|
19
|
+
// coin has no chainId, and every read for it fails rather than returning a
|
|
20
|
+
// balance — so this is fetched once and shared, not guessed per coin.
|
|
21
|
+
let chains;
|
|
22
|
+
const chainRefs = () => {
|
|
23
|
+
if (chains)
|
|
24
|
+
return chains;
|
|
25
|
+
chains = get("/api/v2/vaults/supported-chains").then(supported => {
|
|
26
|
+
const byIdentifier = new Map();
|
|
27
|
+
for (const chain of supported) {
|
|
28
|
+
if (!chain.identifier)
|
|
29
|
+
continue;
|
|
30
|
+
byIdentifier.set(chain.identifier.toLowerCase(), {
|
|
31
|
+
type: chain.type?.toUpperCase() === "SUI" ? "sui" : "evm",
|
|
32
|
+
chainId: chain.networkId,
|
|
33
|
+
identifier: chain.identifier,
|
|
34
|
+
rpcUrl: chain.publicRpcUrl
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
return byIdentifier;
|
|
38
|
+
});
|
|
39
|
+
// Cache the value, not the rejection: one transient 502 here would
|
|
40
|
+
// otherwise fail every later call on this resolver for good.
|
|
41
|
+
chains.catch(() => {
|
|
42
|
+
chains = undefined;
|
|
43
|
+
});
|
|
44
|
+
return chains;
|
|
45
|
+
};
|
|
46
|
+
/** Falls back to the identifier's shape when the catalogue has no entry. */
|
|
47
|
+
const chainRefFor = (identifier, catalogue) => catalogue.get(identifier.toLowerCase()) ?? {
|
|
48
|
+
type: identifier.toLowerCase().startsWith("sui") ? "sui" : "evm",
|
|
49
|
+
identifier
|
|
50
|
+
};
|
|
51
|
+
return {
|
|
52
|
+
async coinsForVault(vaultId) {
|
|
53
|
+
const [vaults, catalogue] = await Promise.all([
|
|
54
|
+
get(`/api/v2/vaults?vaultId=${encodeURIComponent(vaultId)}`),
|
|
55
|
+
chainRefs()
|
|
56
|
+
]);
|
|
57
|
+
const list = Array.isArray(vaults) ? vaults : [vaults];
|
|
58
|
+
const vault = list.find(v => v.id === vaultId) ?? list[0];
|
|
59
|
+
if (!vault)
|
|
60
|
+
throw new Error(`vault ${vaultId} not found`);
|
|
61
|
+
// An ATOMIC vault has no receipt token, but the API still fills
|
|
62
|
+
// receiptCoin with a placeholder so the field never breaks older
|
|
63
|
+
// consumers. Reading it would hand back a coin that does not exist.
|
|
64
|
+
if (vault.vaultType === "ATOMIC") {
|
|
65
|
+
throw new Error(`vault ${vaultId} is atomic and issues no receipt coin`);
|
|
66
|
+
}
|
|
67
|
+
const coins = [];
|
|
68
|
+
for (const [identifier, details] of Object.entries(vault.detailsByChain ?? {})) {
|
|
69
|
+
const receipt = details.receiptCoin;
|
|
70
|
+
if (!receipt?.address)
|
|
71
|
+
continue;
|
|
72
|
+
if (typeof receipt.decimals !== "number") {
|
|
73
|
+
throw new Error(`${receipt.address} has no decimals`);
|
|
74
|
+
}
|
|
75
|
+
const { rpcUrl, ...chain } = chainRefFor(details.chainIdentifier ?? identifier, catalogue);
|
|
76
|
+
coins.push({
|
|
77
|
+
coin: receipt.address,
|
|
78
|
+
chain,
|
|
79
|
+
decimals: receipt.decimals,
|
|
80
|
+
// The wallet balance is not a placement, so it has no
|
|
81
|
+
// pointer to borrow an endpoint from. Carry the published
|
|
82
|
+
// one here or the caller must configure every chain itself.
|
|
83
|
+
rpcUrl,
|
|
84
|
+
symbol: receipt.symbol,
|
|
85
|
+
// longName is empty on every vault the API returns
|
|
86
|
+
// today, and "" is not nullish — ?? would keep it and
|
|
87
|
+
// hand the caller a blank name to render.
|
|
88
|
+
vault: vault.longName || vault.name
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
if (coins.length === 0) {
|
|
92
|
+
throw new Error(`vault ${vaultId} issues no receipt coin`);
|
|
93
|
+
}
|
|
94
|
+
return coins;
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ember-finance/sdk",
|
|
3
3
|
"description": "Ember Protocol SDK",
|
|
4
|
-
"version": "2.
|
|
4
|
+
"version": "2.11.0-pre.1",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"module": "./dist/index.js",
|
|
7
7
|
"main": "./dist/index.js",
|
|
@@ -44,6 +44,11 @@
|
|
|
44
44
|
"import": "./dist/src/common/index.js",
|
|
45
45
|
"default": "./dist/src/common/index.js"
|
|
46
46
|
},
|
|
47
|
+
"./placements": {
|
|
48
|
+
"types": "./dist/src/placements/index.d.ts",
|
|
49
|
+
"import": "./dist/src/placements/index.js",
|
|
50
|
+
"default": "./dist/src/placements/index.js"
|
|
51
|
+
},
|
|
47
52
|
"./abis": {
|
|
48
53
|
"types": "./dist/src/abis/index.d.ts",
|
|
49
54
|
"import": "./dist/src/abis/index.js",
|