@vultisig/core-chain 2.37.0 → 2.38.0
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/CHANGELOG.md +8 -0
- package/dist/chains/solana/kamino/KaminoServiceError.d.ts +63 -0
- package/dist/chains/solana/kamino/KaminoServiceError.d.ts.map +1 -0
- package/dist/chains/solana/kamino/KaminoServiceError.js +29 -0
- package/dist/chains/solana/kamino/KaminoServiceError.js.map +1 -0
- package/dist/chains/solana/kamino/amount.d.ts +141 -0
- package/dist/chains/solana/kamino/amount.d.ts.map +1 -0
- package/dist/chains/solana/kamino/amount.js +156 -0
- package/dist/chains/solana/kamino/amount.js.map +1 -0
- package/dist/chains/solana/kamino/api.d.ts +20 -0
- package/dist/chains/solana/kamino/api.d.ts.map +1 -0
- package/dist/chains/solana/kamino/api.js +59 -0
- package/dist/chains/solana/kamino/api.js.map +1 -0
- package/dist/chains/solana/kamino/baseUnits.d.ts +23 -0
- package/dist/chains/solana/kamino/baseUnits.d.ts.map +1 -0
- package/dist/chains/solana/kamino/baseUnits.js +30 -0
- package/dist/chains/solana/kamino/baseUnits.js.map +1 -0
- package/dist/chains/solana/kamino/config.d.ts +27 -0
- package/dist/chains/solana/kamino/config.d.ts.map +1 -0
- package/dist/chains/solana/kamino/config.js +27 -0
- package/dist/chains/solana/kamino/config.js.map +1 -0
- package/dist/chains/solana/kamino/decimal.d.ts +24 -0
- package/dist/chains/solana/kamino/decimal.d.ts.map +1 -0
- package/dist/chains/solana/kamino/decimal.js +52 -0
- package/dist/chains/solana/kamino/decimal.js.map +1 -0
- package/dist/chains/solana/kamino/models.d.ts +148 -0
- package/dist/chains/solana/kamino/models.d.ts.map +1 -0
- package/dist/chains/solana/kamino/models.js +2 -0
- package/dist/chains/solana/kamino/models.js.map +1 -0
- package/dist/chains/solana/kamino/position.d.ts +79 -0
- package/dist/chains/solana/kamino/position.d.ts.map +1 -0
- package/dist/chains/solana/kamino/position.js +52 -0
- package/dist/chains/solana/kamino/position.js.map +1 -0
- package/dist/chains/solana/kamino/rate.d.ts +57 -0
- package/dist/chains/solana/kamino/rate.d.ts.map +1 -0
- package/dist/chains/solana/kamino/rate.js +88 -0
- package/dist/chains/solana/kamino/rate.js.map +1 -0
- package/dist/chains/solana/kamino/registry.d.ts +70 -0
- package/dist/chains/solana/kamino/registry.d.ts.map +1 -0
- package/dist/chains/solana/kamino/registry.js +67 -0
- package/dist/chains/solana/kamino/registry.js.map +1 -0
- package/dist/chains/solana/kamino/tx/actions.d.ts +22 -0
- package/dist/chains/solana/kamino/tx/actions.d.ts.map +1 -0
- package/dist/chains/solana/kamino/tx/actions.js +85 -0
- package/dist/chains/solana/kamino/tx/actions.js.map +1 -0
- package/dist/chains/solana/kamino/tx/computeBudget.d.ts +66 -0
- package/dist/chains/solana/kamino/tx/computeBudget.d.ts.map +1 -0
- package/dist/chains/solana/kamino/tx/computeBudget.js +73 -0
- package/dist/chains/solana/kamino/tx/computeBudget.js.map +1 -0
- package/dist/chains/solana/kamino/tx/decode.d.ts +121 -0
- package/dist/chains/solana/kamino/tx/decode.d.ts.map +1 -0
- package/dist/chains/solana/kamino/tx/decode.js +458 -0
- package/dist/chains/solana/kamino/tx/decode.js.map +1 -0
- package/dist/chains/solana/kamino/tx/instructions.d.ts +260 -0
- package/dist/chains/solana/kamino/tx/instructions.d.ts.map +1 -0
- package/dist/chains/solana/kamino/tx/instructions.js +256 -0
- package/dist/chains/solana/kamino/tx/instructions.js.map +1 -0
- package/dist/chains/solana/kamino/tx/sequence.d.ts +123 -0
- package/dist/chains/solana/kamino/tx/sequence.d.ts.map +1 -0
- package/dist/chains/solana/kamino/tx/sequence.js +235 -0
- package/dist/chains/solana/kamino/tx/sequence.js.map +1 -0
- package/dist/chains/solana/kamino/tx/validate.d.ts +138 -0
- package/dist/chains/solana/kamino/tx/validate.d.ts.map +1 -0
- package/dist/chains/solana/kamino/tx/validate.js +542 -0
- package/dist/chains/solana/kamino/tx/validate.js.map +1 -0
- package/dist/chains/solana/kamino/tx/wire.d.ts +107 -0
- package/dist/chains/solana/kamino/tx/wire.d.ts.map +1 -0
- package/dist/chains/solana/kamino/tx/wire.js +274 -0
- package/dist/chains/solana/kamino/tx/wire.js.map +1 -0
- package/dist/chains/solana/kamino/vaultInfo.d.ts +17 -0
- package/dist/chains/solana/kamino/vaultInfo.d.ts.map +1 -0
- package/dist/chains/solana/kamino/vaultInfo.js +150 -0
- package/dist/chains/solana/kamino/vaultInfo.js.map +1 -0
- package/package.json +91 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# @vultisig/core-chain
|
|
2
2
|
|
|
3
|
+
## 2.38.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#2074](https://github.com/vultisig/vultisig-sdk/pull/2074) [`8929244`](https://github.com/vultisig/vultisig-sdk/commit/8929244cdb3b21059a46eabac6d4d9684e18a633) Thanks [@Ehsan-saradar](https://github.com/Ehsan-saradar)! - Add the Kamino Earn data layer under `chains/solana/kamino`: a REST client for the kVaults API (vault state, metrics, user positions, PnL) with a typed error envelope that separates retryable statuses from permanent refusals; a curated vault registry pinning each launch vault's identity (mints, decimals, farm, curator, risk tier); distinct token- and share-denominated amount types over exact `bigint` base units, with exact-rate conversions that truncate toward zero so a sized withdraw can never over-request (the API rewrites an over-sized withdraw to `u64::MAX` — withdraw everything); vault-info hydration that refuses responses disagreeing with the pinned identity and derives the effective deposit/withdraw minimums the on-chain program actually accepts; and position parsing with a spendable-balance rule that stays strictly below the reported balance.
|
|
8
|
+
|
|
9
|
+
- [#2124](https://github.com/vultisig/vultisig-sdk/pull/2124) [`514e31f`](https://github.com/vultisig/vultisig-sdk/commit/514e31f084c241792f3a9b2436074c324a909c0f) Thanks [@Ehsan-saradar](https://github.com/Ehsan-saradar)! - Add the Kamino Earn transaction pipeline under `chains/solana/kamino/tx`: build the unsigned deposit/withdraw transactions (with the withdraw-everything sentinel refused before a request leaves the device); inject the attribution memo and the compute-budget pair into the built v0 transaction without disturbing address-lookup-table indexes; replace the recent blockhash immediately before keysign; a fail-closed validator that admits only allow-listed programs, matches the exact instruction sequence each operation produces (both withdraw discriminators, the farms unstake pair, exactly one memo carrying exactly the attribution tag), pins every account that decides where money goes against the registry and local ATA/PDA derivations, pins every spend amount, and refuses unexplained writable accounts; and an offline decoder that lets a co-signing device derive an independent claim about what the bytes do — vault identified through the signer's own share account, both withdraw shapes accepted, the farm release bounded by the withdraw itself.
|
|
10
|
+
|
|
3
11
|
## 2.37.0
|
|
4
12
|
|
|
5
13
|
### Minor Changes
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Why a Kamino service call was refused or failed, as a record union so
|
|
3
|
+
* callers can branch with `matchRecordUnion`.
|
|
4
|
+
*/
|
|
5
|
+
export type KaminoServiceErrorReason = {
|
|
6
|
+
/**
|
|
7
|
+
* A structured error from the API. `status` is retained alongside the
|
|
8
|
+
* machine-readable `code` (`KVAULT_NOT_FOUND`, `TRANSACTION_SIZE_ERROR`,
|
|
9
|
+
* …) because Kamino's error envelope carries a `statusCode` of its own
|
|
10
|
+
* and a retryable 503 can arrive in the same body shape as a permanent
|
|
11
|
+
* 400.
|
|
12
|
+
*/
|
|
13
|
+
api: {
|
|
14
|
+
status: number;
|
|
15
|
+
code?: string;
|
|
16
|
+
message: string;
|
|
17
|
+
};
|
|
18
|
+
} | {
|
|
19
|
+
/** A numeric field did not parse under the strict decimal rules. */
|
|
20
|
+
malformedNumber: {
|
|
21
|
+
field: string;
|
|
22
|
+
value: string;
|
|
23
|
+
};
|
|
24
|
+
} | {
|
|
25
|
+
/**
|
|
26
|
+
* An amount could not be sent: non-positive, beyond the `u64` an
|
|
27
|
+
* on-chain instruction can carry, or at an implausible decimal scale.
|
|
28
|
+
*/
|
|
29
|
+
invalidAmount: string;
|
|
30
|
+
} | {
|
|
31
|
+
/**
|
|
32
|
+
* A vault was described to the service in terms the registry does not
|
|
33
|
+
* recognise. The curated entry is the app's record of a vault's
|
|
34
|
+
* identity; anything else cannot be used to size or target a
|
|
35
|
+
* transaction.
|
|
36
|
+
*/
|
|
37
|
+
vaultNotInRegistry: string;
|
|
38
|
+
} | {
|
|
39
|
+
/**
|
|
40
|
+
* The API described a vault differently from the registry. Mints, their
|
|
41
|
+
* decimals and the farm are immutable properties of a kVault, so a
|
|
42
|
+
* disagreement is either the wrong vault or a response that cannot be
|
|
43
|
+
* trusted to size or target a transaction.
|
|
44
|
+
*/
|
|
45
|
+
vaultMetadataMismatch: {
|
|
46
|
+
field: string;
|
|
47
|
+
expected: string;
|
|
48
|
+
actual: string;
|
|
49
|
+
};
|
|
50
|
+
};
|
|
51
|
+
/**
|
|
52
|
+
* Typed failure from the Kamino service boundary. Carries a structured
|
|
53
|
+
* `reason` so callers branch on data instead of matching message text, and
|
|
54
|
+
* `isRetryable` so a transient 429/5xx can be told apart from a permanent
|
|
55
|
+
* refusal that arrived in the same shape.
|
|
56
|
+
*/
|
|
57
|
+
export declare class KaminoServiceError extends Error {
|
|
58
|
+
readonly reason: KaminoServiceErrorReason;
|
|
59
|
+
constructor(reason: KaminoServiceErrorReason);
|
|
60
|
+
/** Whether retrying the same request could plausibly succeed. */
|
|
61
|
+
get isRetryable(): boolean;
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=KaminoServiceError.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"KaminoServiceError.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/chain/chains/solana/kamino/KaminoServiceError.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,MAAM,MAAM,wBAAwB,GAChC;IACE;;;;;;OAMG;IACH,GAAG,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAA;CACxD,GACD;IACE,oEAAoE;IACpE,eAAe,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAA;CAClD,GACD;IACE;;;OAGG;IACH,aAAa,EAAE,MAAM,CAAA;CACtB,GACD;IACE;;;;;OAKG;IACH,kBAAkB,EAAE,MAAM,CAAA;CAC3B,GACD;IACE;;;;;OAKG;IACH,qBAAqB,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAA;CAC3E,CAAA;AAEL;;;;;GAKG;AACH,qBAAa,kBAAmB,SAAQ,KAAK;IAC3C,QAAQ,CAAC,MAAM,EAAE,wBAAwB,CAAA;gBAE7B,MAAM,EAAE,wBAAwB;IAe5C,iEAAiE;IACjE,IAAI,WAAW,IAAI,OAAO,CAIzB;CACF"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { matchRecordUnion } from '@vultisig/lib-utils/matchRecordUnion';
|
|
2
|
+
/**
|
|
3
|
+
* Typed failure from the Kamino service boundary. Carries a structured
|
|
4
|
+
* `reason` so callers branch on data instead of matching message text, and
|
|
5
|
+
* `isRetryable` so a transient 429/5xx can be told apart from a permanent
|
|
6
|
+
* refusal that arrived in the same shape.
|
|
7
|
+
*/
|
|
8
|
+
export class KaminoServiceError extends Error {
|
|
9
|
+
reason;
|
|
10
|
+
constructor(reason) {
|
|
11
|
+
super(matchRecordUnion(reason, {
|
|
12
|
+
api: ({ code, message }) => (code ? `${code}: ${message}` : message),
|
|
13
|
+
malformedNumber: ({ field, value }) => `Malformed Kamino number for ${field}: ${value}`,
|
|
14
|
+
invalidAmount: detail => `Invalid Kamino amount: ${detail}`,
|
|
15
|
+
vaultNotInRegistry: address => `Kamino vault not in registry: ${address}`,
|
|
16
|
+
vaultMetadataMismatch: ({ field, expected, actual }) => `Kamino vault ${field} is "${actual}", registry pins "${expected}"`,
|
|
17
|
+
}));
|
|
18
|
+
this.name = 'KaminoServiceError';
|
|
19
|
+
this.reason = reason;
|
|
20
|
+
}
|
|
21
|
+
/** Whether retrying the same request could plausibly succeed. */
|
|
22
|
+
get isRetryable() {
|
|
23
|
+
if (!('api' in this.reason))
|
|
24
|
+
return false;
|
|
25
|
+
const { status } = this.reason.api;
|
|
26
|
+
return status === 429 || (status >= 500 && status <= 599);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=KaminoServiceError.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"KaminoServiceError.js","sourceRoot":"","sources":["../../../../../../../packages/core/chain/chains/solana/kamino/KaminoServiceError.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,sCAAsC,CAAA;AA+CvE;;;;;GAKG;AACH,MAAM,OAAO,kBAAmB,SAAQ,KAAK;IAClC,MAAM,CAA0B;IAEzC,YAAY,MAAgC;QAC1C,KAAK,CACH,gBAAgB,CAAC,MAAM,EAAE;YACvB,GAAG,EAAE,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,KAAK,OAAO,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;YACpE,eAAe,EAAE,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,+BAA+B,KAAK,KAAK,KAAK,EAAE;YACvF,aAAa,EAAE,MAAM,CAAC,EAAE,CAAC,0BAA0B,MAAM,EAAE;YAC3D,kBAAkB,EAAE,OAAO,CAAC,EAAE,CAAC,iCAAiC,OAAO,EAAE;YACzE,qBAAqB,EAAE,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,CACrD,gBAAgB,KAAK,QAAQ,MAAM,qBAAqB,QAAQ,GAAG;SACtE,CAAC,CACH,CAAA;QACD,IAAI,CAAC,IAAI,GAAG,oBAAoB,CAAA;QAChC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAA;IACtB,CAAC;IAED,iEAAiE;IACjE,IAAI,WAAW;QACb,IAAI,CAAC,CAAC,KAAK,IAAI,IAAI,CAAC,MAAM,CAAC;YAAE,OAAO,KAAK,CAAA;QACzC,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAA;QAClC,OAAO,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,IAAI,GAAG,IAAI,MAAM,IAAI,GAAG,CAAC,CAAA;IAC3D,CAAC;CACF"}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { KaminoRate } from './rate.js';
|
|
2
|
+
/**
|
|
3
|
+
* An amount denominated in a vault's **underlying token** (USDC, SOL).
|
|
4
|
+
*
|
|
5
|
+
* This is what `POST /ktx/kvault/deposit` expects. Deposit and withdraw take
|
|
6
|
+
* the same `amount` JSON field with inverted units — deposit in tokens,
|
|
7
|
+
* withdraw in shares — so the two are separate types on purpose: passing one
|
|
8
|
+
* where the other belongs is a compile error rather than a silently mis-sized
|
|
9
|
+
* transaction. The `unit` discriminant is what makes that hold under
|
|
10
|
+
* structural typing.
|
|
11
|
+
*/
|
|
12
|
+
export type KaminoTokenAmount = {
|
|
13
|
+
unit: 'kaminoToken';
|
|
14
|
+
/** The exact on-chain integer; every other form is derived from it. */
|
|
15
|
+
baseUnits: bigint;
|
|
16
|
+
decimals: number;
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* An amount denominated in a vault's **share token** (kTokens).
|
|
20
|
+
*
|
|
21
|
+
* This is what `POST /ktx/kvault/withdraw` expects — see `KaminoTokenAmount`
|
|
22
|
+
* for why the units are two distinct types.
|
|
23
|
+
*/
|
|
24
|
+
export type KaminoShareAmount = {
|
|
25
|
+
unit: 'kaminoShare';
|
|
26
|
+
/** The exact on-chain integer; every other form is derived from it. */
|
|
27
|
+
baseUnits: bigint;
|
|
28
|
+
decimals: number;
|
|
29
|
+
};
|
|
30
|
+
/** Either Kamino amount unit; use where behaviour is unit-independent. */
|
|
31
|
+
export type KaminoAmount = KaminoTokenAmount | KaminoShareAmount;
|
|
32
|
+
/** Wraps base units as a token amount. */
|
|
33
|
+
export declare const kaminoTokenAmount: (baseUnits: bigint, decimals: number) => KaminoTokenAmount;
|
|
34
|
+
/** Wraps base units as a share amount. */
|
|
35
|
+
export declare const kaminoShareAmount: (baseUnits: bigint, decimals: number) => KaminoShareAmount;
|
|
36
|
+
/**
|
|
37
|
+
* Parses a base-unit integer string as it appears in vault state (e.g.
|
|
38
|
+
* `minDepositAmount = "100000"` for 0.1 USDC). The caller supplies the scale,
|
|
39
|
+
* because the response never says which of the two mints a figure belongs to.
|
|
40
|
+
*/
|
|
41
|
+
export declare const kaminoTokenAmountFromBaseUnitString: (raw: string, decimals: number) => KaminoTokenAmount | undefined;
|
|
42
|
+
/**
|
|
43
|
+
* Parses a human-units token decimal string as returned by the metrics
|
|
44
|
+
* endpoint (e.g. `tokensAvailable = "9581.812345"`), exactly, truncating
|
|
45
|
+
* toward zero below the mint's scale.
|
|
46
|
+
*/
|
|
47
|
+
export declare const kaminoTokenAmountFromDecimalString: (raw: string, decimals: number) => KaminoTokenAmount | undefined;
|
|
48
|
+
/**
|
|
49
|
+
* Parses a human-units share decimal string as returned by
|
|
50
|
+
* `GET /kvaults/users/{owner}/positions` (e.g. `"517536.857982"`), exactly,
|
|
51
|
+
* truncating toward zero below the mint's scale.
|
|
52
|
+
*/
|
|
53
|
+
export declare const kaminoShareAmountFromDecimalString: (raw: string, decimals: number) => KaminoShareAmount | undefined;
|
|
54
|
+
/**
|
|
55
|
+
* Whether this amount may be sent to Kamino: strictly positive, expressible as
|
|
56
|
+
* a `u64`, and at a sane decimal scale. The API accepts anything it can parse
|
|
57
|
+
* — a below-minimum deposit builds a transaction that fails on-chain, and an
|
|
58
|
+
* over-sized withdraw is rewritten to `u64::MAX`, meaning withdraw everything
|
|
59
|
+
* — so bounds are enforced client-side; this is the only gate the API offers.
|
|
60
|
+
*/
|
|
61
|
+
export declare const isValidKaminoRequestAmount: ({ baseUnits, decimals }: KaminoAmount) => boolean;
|
|
62
|
+
/**
|
|
63
|
+
* The value as Kamino's request bodies want it: a plain human-units decimal
|
|
64
|
+
* string with no grouping, no trailing zeros and no exponent.
|
|
65
|
+
*/
|
|
66
|
+
export declare const kaminoAmountApiString: ({ baseUnits, decimals }: KaminoAmount) => string;
|
|
67
|
+
/**
|
|
68
|
+
* Rescales an exact rate to base units at `toDecimals`, truncating toward
|
|
69
|
+
* zero, plus whether anything was truncated away. `undefined` when the scale
|
|
70
|
+
* is implausible or the value negative.
|
|
71
|
+
*
|
|
72
|
+
* The exactness flag exists for one caller and one reason. `/positions`
|
|
73
|
+
* reports share balances at up to 14 decimal places while a share mint has 6,
|
|
74
|
+
* so the truncated figure is *strictly below* the real balance whenever there
|
|
75
|
+
* were extra digits — and exactly equal to it when there were not. The
|
|
76
|
+
* withdraw maximum has to be strictly below, so it needs to know which of the
|
|
77
|
+
* two happened. See `parseKaminoSharePosition`.
|
|
78
|
+
*/
|
|
79
|
+
export declare const scaleKaminoRate: ({ rate, toDecimals, }: {
|
|
80
|
+
rate: KaminoRate;
|
|
81
|
+
toDecimals: number;
|
|
82
|
+
}) => {
|
|
83
|
+
baseUnits: bigint;
|
|
84
|
+
isExact: boolean;
|
|
85
|
+
} | undefined;
|
|
86
|
+
type ShareToTokenInput = {
|
|
87
|
+
shares: KaminoShareAmount;
|
|
88
|
+
/**
|
|
89
|
+
* Underlying tokens per share — `metrics.tokensPerShare`, never
|
|
90
|
+
* `metrics.sharePrice`, which is USD-denominated and only coincides with it
|
|
91
|
+
* on dollar-pegged vaults (Allez SOL: `sharePrice` 0.0794 vs `tokensPerShare`
|
|
92
|
+
* 0.0010749).
|
|
93
|
+
*/
|
|
94
|
+
tokensPerShare: KaminoRate;
|
|
95
|
+
tokenDecimals: number;
|
|
96
|
+
};
|
|
97
|
+
/**
|
|
98
|
+
* The position's value in the underlying token: `shares × tokensPerShare`,
|
|
99
|
+
* computed in exact integer arithmetic and truncated toward zero.
|
|
100
|
+
*/
|
|
101
|
+
export declare const kaminoShareToTokenValue: (input: ShareToTokenInput) => KaminoTokenAmount | undefined;
|
|
102
|
+
/**
|
|
103
|
+
* The same conversion rounded **up**.
|
|
104
|
+
*
|
|
105
|
+
* Used for one thing only: rendering a share-denominated *minimum* as an asset
|
|
106
|
+
* amount, so the displayed figure, converted back, still clears the minimum.
|
|
107
|
+
* Never use this to size a transaction: rounding up is exactly the direction
|
|
108
|
+
* that turns a partial withdraw into an over-request.
|
|
109
|
+
*/
|
|
110
|
+
export declare const kaminoShareToTokenValueRoundedUp: (input: ShareToTokenInput) => KaminoTokenAmount | undefined;
|
|
111
|
+
type TokenToShareInput = {
|
|
112
|
+
tokens: KaminoTokenAmount;
|
|
113
|
+
/** Underlying tokens per share — see `ShareToTokenInput.tokensPerShare`. */
|
|
114
|
+
tokensPerShare: KaminoRate;
|
|
115
|
+
shareDecimals: number;
|
|
116
|
+
};
|
|
117
|
+
/**
|
|
118
|
+
* Converts a token amount into the share amount a withdraw actually burns:
|
|
119
|
+
* `shares = tokens / tokensPerShare`, truncated toward zero.
|
|
120
|
+
*
|
|
121
|
+
* Exact integer arithmetic, never floating point. Rounding down is a safety
|
|
122
|
+
* property, not a preference: the API does not validate the amount, and a
|
|
123
|
+
* withdraw larger than the user's share balance is silently rewritten to
|
|
124
|
+
* `u64::MAX` — "withdraw everything". A division that rounded up, even by one
|
|
125
|
+
* base unit at the far end of the mantissa, could turn a partial withdraw into
|
|
126
|
+
* a full exit. For the same reason a 100% withdraw must send the held share
|
|
127
|
+
* balance directly and never a number derived from here.
|
|
128
|
+
*/
|
|
129
|
+
export declare const kaminoTokenToShareAmount: (input: TokenToShareInput) => KaminoShareAmount | undefined;
|
|
130
|
+
/**
|
|
131
|
+
* The same conversion rounded **up**.
|
|
132
|
+
*
|
|
133
|
+
* Used for one thing only: turning a token-denominated *minimum* into the
|
|
134
|
+
* share count a withdraw has to name to clear it. Rounding down there would
|
|
135
|
+
* produce a share figure worth fractionally less than the minimum, which is
|
|
136
|
+
* the whole bug this exists to avoid. Never use it to size a transaction —
|
|
137
|
+
* see `kaminoTokenToShareAmount` for what an over-request becomes.
|
|
138
|
+
*/
|
|
139
|
+
export declare const kaminoTokenToShareAmountRoundedUp: (input: TokenToShareInput) => KaminoShareAmount | undefined;
|
|
140
|
+
export {};
|
|
141
|
+
//# sourceMappingURL=amount.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"amount.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/chain/chains/solana/kamino/amount.ts"],"names":[],"mappings":"AACA,OAAO,EAAwB,UAAU,EAAmB,MAAM,QAAQ,CAAA;AAE1E;;;;;;;;;GASG;AACH,MAAM,MAAM,iBAAiB,GAAG;IAC9B,IAAI,EAAE,aAAa,CAAA;IACnB,uEAAuE;IACvE,SAAS,EAAE,MAAM,CAAA;IACjB,QAAQ,EAAE,MAAM,CAAA;CACjB,CAAA;AAED;;;;;GAKG;AACH,MAAM,MAAM,iBAAiB,GAAG;IAC9B,IAAI,EAAE,aAAa,CAAA;IACnB,uEAAuE;IACvE,SAAS,EAAE,MAAM,CAAA;IACjB,QAAQ,EAAE,MAAM,CAAA;CACjB,CAAA;AAED,0EAA0E;AAC1E,MAAM,MAAM,YAAY,GAAG,iBAAiB,GAAG,iBAAiB,CAAA;AAEhE,0CAA0C;AAC1C,eAAO,MAAM,iBAAiB,GAAI,WAAW,MAAM,EAAE,UAAU,MAAM,KAAG,iBAItE,CAAA;AAEF,0CAA0C;AAC1C,eAAO,MAAM,iBAAiB,GAAI,WAAW,MAAM,EAAE,UAAU,MAAM,KAAG,iBAItE,CAAA;AAEF;;;;GAIG;AACH,eAAO,MAAM,mCAAmC,GAAI,KAAK,MAAM,EAAE,UAAU,MAAM,KAAG,iBAAiB,GAAG,SAGvG,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,kCAAkC,GAAI,KAAK,MAAM,EAAE,UAAU,MAAM,KAAG,iBAAiB,GAAG,SAKtG,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,kCAAkC,GAAI,KAAK,MAAM,EAAE,UAAU,MAAM,KAAG,iBAAiB,GAAG,SAKtG,CAAA;AAED;;;;;;GAMG;AACH,eAAO,MAAM,0BAA0B,GAAI,yBAAyB,YAAY,KAAG,OACkB,CAAA;AAErG;;;GAGG;AACH,eAAO,MAAM,qBAAqB,GAAI,yBAAyB,YAAY,KAAG,MAC9B,CAAA;AAEhD;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,eAAe,GAAI,uBAG7B;IACD,IAAI,EAAE,UAAU,CAAA;IAChB,UAAU,EAAE,MAAM,CAAA;CACnB,KAAG;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,GAAG,SAU7C,CAAA;AAED,KAAK,iBAAiB,GAAG;IACvB,MAAM,EAAE,iBAAiB,CAAA;IACzB;;;;;OAKG;IACH,cAAc,EAAE,UAAU,CAAA;IAC1B,aAAa,EAAE,MAAM,CAAA;CACtB,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,uBAAuB,GAAI,OAAO,iBAAiB,KAAG,iBAAiB,GAAG,SAC3D,CAAA;AAE5B;;;;;;;GAOG;AACH,eAAO,MAAM,gCAAgC,GAAI,OAAO,iBAAiB,KAAG,iBAAiB,GAAG,SACrE,CAAA;AAE3B,KAAK,iBAAiB,GAAG;IACvB,MAAM,EAAE,iBAAiB,CAAA;IACzB,4EAA4E;IAC5E,cAAc,EAAE,UAAU,CAAA;IAC1B,aAAa,EAAE,MAAM,CAAA;CACtB,CAAA;AAED;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,wBAAwB,GAAI,OAAO,iBAAiB,KAAG,iBAAiB,GAAG,SAC5D,CAAA;AAE5B;;;;;;;;GAQG;AACH,eAAO,MAAM,iCAAiC,GAAI,OAAO,iBAAiB,KAAG,iBAAiB,GAAG,SACtE,CAAA"}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import { kaminoMaxBaseUnits, kaminoMaxDecimals, renderKaminoBaseUnits } from './baseUnits.js';
|
|
2
|
+
import { isPositiveKaminoRate, parseKaminoRate } from './rate.js';
|
|
3
|
+
/** Wraps base units as a token amount. */
|
|
4
|
+
export const kaminoTokenAmount = (baseUnits, decimals) => ({
|
|
5
|
+
unit: 'kaminoToken',
|
|
6
|
+
baseUnits,
|
|
7
|
+
decimals,
|
|
8
|
+
});
|
|
9
|
+
/** Wraps base units as a share amount. */
|
|
10
|
+
export const kaminoShareAmount = (baseUnits, decimals) => ({
|
|
11
|
+
unit: 'kaminoShare',
|
|
12
|
+
baseUnits,
|
|
13
|
+
decimals,
|
|
14
|
+
});
|
|
15
|
+
/**
|
|
16
|
+
* Parses a base-unit integer string as it appears in vault state (e.g.
|
|
17
|
+
* `minDepositAmount = "100000"` for 0.1 USDC). The caller supplies the scale,
|
|
18
|
+
* because the response never says which of the two mints a figure belongs to.
|
|
19
|
+
*/
|
|
20
|
+
export const kaminoTokenAmountFromBaseUnitString = (raw, decimals) => {
|
|
21
|
+
const baseUnits = parseBaseUnitString(raw);
|
|
22
|
+
return baseUnits === undefined ? undefined : kaminoTokenAmount(baseUnits, decimals);
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Parses a human-units token decimal string as returned by the metrics
|
|
26
|
+
* endpoint (e.g. `tokensAvailable = "9581.812345"`), exactly, truncating
|
|
27
|
+
* toward zero below the mint's scale.
|
|
28
|
+
*/
|
|
29
|
+
export const kaminoTokenAmountFromDecimalString = (raw, decimals) => {
|
|
30
|
+
const rate = parseKaminoRate(raw);
|
|
31
|
+
if (!rate)
|
|
32
|
+
return undefined;
|
|
33
|
+
const scaled = scaleKaminoRate({ rate, toDecimals: decimals });
|
|
34
|
+
return scaled === undefined ? undefined : kaminoTokenAmount(scaled.baseUnits, decimals);
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* Parses a human-units share decimal string as returned by
|
|
38
|
+
* `GET /kvaults/users/{owner}/positions` (e.g. `"517536.857982"`), exactly,
|
|
39
|
+
* truncating toward zero below the mint's scale.
|
|
40
|
+
*/
|
|
41
|
+
export const kaminoShareAmountFromDecimalString = (raw, decimals) => {
|
|
42
|
+
const rate = parseKaminoRate(raw);
|
|
43
|
+
if (!rate)
|
|
44
|
+
return undefined;
|
|
45
|
+
const scaled = scaleKaminoRate({ rate, toDecimals: decimals });
|
|
46
|
+
return scaled === undefined ? undefined : kaminoShareAmount(scaled.baseUnits, decimals);
|
|
47
|
+
};
|
|
48
|
+
/**
|
|
49
|
+
* Whether this amount may be sent to Kamino: strictly positive, expressible as
|
|
50
|
+
* a `u64`, and at a sane decimal scale. The API accepts anything it can parse
|
|
51
|
+
* — a below-minimum deposit builds a transaction that fails on-chain, and an
|
|
52
|
+
* over-sized withdraw is rewritten to `u64::MAX`, meaning withdraw everything
|
|
53
|
+
* — so bounds are enforced client-side; this is the only gate the API offers.
|
|
54
|
+
*/
|
|
55
|
+
export const isValidKaminoRequestAmount = ({ baseUnits, decimals }) => baseUnits > 0n && baseUnits <= kaminoMaxBaseUnits && decimals >= 0 && decimals <= kaminoMaxDecimals;
|
|
56
|
+
/**
|
|
57
|
+
* The value as Kamino's request bodies want it: a plain human-units decimal
|
|
58
|
+
* string with no grouping, no trailing zeros and no exponent.
|
|
59
|
+
*/
|
|
60
|
+
export const kaminoAmountApiString = ({ baseUnits, decimals }) => renderKaminoBaseUnits({ baseUnits, decimals });
|
|
61
|
+
/**
|
|
62
|
+
* Rescales an exact rate to base units at `toDecimals`, truncating toward
|
|
63
|
+
* zero, plus whether anything was truncated away. `undefined` when the scale
|
|
64
|
+
* is implausible or the value negative.
|
|
65
|
+
*
|
|
66
|
+
* The exactness flag exists for one caller and one reason. `/positions`
|
|
67
|
+
* reports share balances at up to 14 decimal places while a share mint has 6,
|
|
68
|
+
* so the truncated figure is *strictly below* the real balance whenever there
|
|
69
|
+
* were extra digits — and exactly equal to it when there were not. The
|
|
70
|
+
* withdraw maximum has to be strictly below, so it needs to know which of the
|
|
71
|
+
* two happened. See `parseKaminoSharePosition`.
|
|
72
|
+
*/
|
|
73
|
+
export const scaleKaminoRate = ({ rate, toDecimals, }) => {
|
|
74
|
+
if (toDecimals < 0 || toDecimals > kaminoMaxDecimals)
|
|
75
|
+
return undefined;
|
|
76
|
+
if (rate.scale < 0 || rate.scale > kaminoMaxDecimals * 4)
|
|
77
|
+
return undefined;
|
|
78
|
+
if (rate.numerator < 0n)
|
|
79
|
+
return undefined;
|
|
80
|
+
if (toDecimals >= rate.scale) {
|
|
81
|
+
return { baseUnits: rate.numerator * 10n ** BigInt(toDecimals - rate.scale), isExact: true };
|
|
82
|
+
}
|
|
83
|
+
const divisor = 10n ** BigInt(rate.scale - toDecimals);
|
|
84
|
+
return { baseUnits: rate.numerator / divisor, isExact: rate.numerator % divisor === 0n };
|
|
85
|
+
};
|
|
86
|
+
/**
|
|
87
|
+
* The position's value in the underlying token: `shares × tokensPerShare`,
|
|
88
|
+
* computed in exact integer arithmetic and truncated toward zero.
|
|
89
|
+
*/
|
|
90
|
+
export const kaminoShareToTokenValue = (input) => shareToToken(input, false);
|
|
91
|
+
/**
|
|
92
|
+
* The same conversion rounded **up**.
|
|
93
|
+
*
|
|
94
|
+
* Used for one thing only: rendering a share-denominated *minimum* as an asset
|
|
95
|
+
* amount, so the displayed figure, converted back, still clears the minimum.
|
|
96
|
+
* Never use this to size a transaction: rounding up is exactly the direction
|
|
97
|
+
* that turns a partial withdraw into an over-request.
|
|
98
|
+
*/
|
|
99
|
+
export const kaminoShareToTokenValueRoundedUp = (input) => shareToToken(input, true);
|
|
100
|
+
/**
|
|
101
|
+
* Converts a token amount into the share amount a withdraw actually burns:
|
|
102
|
+
* `shares = tokens / tokensPerShare`, truncated toward zero.
|
|
103
|
+
*
|
|
104
|
+
* Exact integer arithmetic, never floating point. Rounding down is a safety
|
|
105
|
+
* property, not a preference: the API does not validate the amount, and a
|
|
106
|
+
* withdraw larger than the user's share balance is silently rewritten to
|
|
107
|
+
* `u64::MAX` — "withdraw everything". A division that rounded up, even by one
|
|
108
|
+
* base unit at the far end of the mantissa, could turn a partial withdraw into
|
|
109
|
+
* a full exit. For the same reason a 100% withdraw must send the held share
|
|
110
|
+
* balance directly and never a number derived from here.
|
|
111
|
+
*/
|
|
112
|
+
export const kaminoTokenToShareAmount = (input) => tokenToShare(input, false);
|
|
113
|
+
/**
|
|
114
|
+
* The same conversion rounded **up**.
|
|
115
|
+
*
|
|
116
|
+
* Used for one thing only: turning a token-denominated *minimum* into the
|
|
117
|
+
* share count a withdraw has to name to clear it. Rounding down there would
|
|
118
|
+
* produce a share figure worth fractionally less than the minimum, which is
|
|
119
|
+
* the whole bug this exists to avoid. Never use it to size a transaction —
|
|
120
|
+
* see `kaminoTokenToShareAmount` for what an over-request becomes.
|
|
121
|
+
*/
|
|
122
|
+
export const kaminoTokenToShareAmountRoundedUp = (input) => tokenToShare(input, true);
|
|
123
|
+
const shareToToken = ({ shares, tokensPerShare, tokenDecimals }, roundUp) => {
|
|
124
|
+
if (!isConvertible(tokensPerShare, shares.baseUnits, [tokenDecimals, shares.decimals]))
|
|
125
|
+
return undefined;
|
|
126
|
+
// tokens = shares × rate, in base units:
|
|
127
|
+
// tokensBase = sharesBase × numerator × 10^tokenDecimals
|
|
128
|
+
// ÷ (10^shareDecimals × 10^rateScale)
|
|
129
|
+
const numerator = shares.baseUnits * tokensPerShare.numerator * 10n ** BigInt(tokenDecimals);
|
|
130
|
+
const denominator = 10n ** BigInt(shares.decimals + tokensPerShare.scale);
|
|
131
|
+
return kaminoTokenAmount(divide(numerator, denominator, roundUp), tokenDecimals);
|
|
132
|
+
};
|
|
133
|
+
const tokenToShare = ({ tokens, tokensPerShare, shareDecimals }, roundUp) => {
|
|
134
|
+
if (!isConvertible(tokensPerShare, tokens.baseUnits, [shareDecimals, tokens.decimals]))
|
|
135
|
+
return undefined;
|
|
136
|
+
// shares = tokens ÷ rate, in base units:
|
|
137
|
+
// sharesBase = tokensBase × 10^rateScale × 10^shareDecimals
|
|
138
|
+
// ÷ (10^tokenDecimals × numerator)
|
|
139
|
+
const numerator = tokens.baseUnits * 10n ** BigInt(tokensPerShare.scale + shareDecimals);
|
|
140
|
+
const denominator = 10n ** BigInt(tokens.decimals) * tokensPerShare.numerator;
|
|
141
|
+
return kaminoShareAmount(divide(numerator, denominator, roundUp), shareDecimals);
|
|
142
|
+
};
|
|
143
|
+
const isConvertible = (rate, baseUnits, decimalScales) => isPositiveKaminoRate(rate) &&
|
|
144
|
+
baseUnits >= 0n &&
|
|
145
|
+
rate.scale >= 0 &&
|
|
146
|
+
rate.scale <= kaminoMaxDecimals * 4 &&
|
|
147
|
+
decimalScales.every(decimals => decimals >= 0 && decimals <= kaminoMaxDecimals);
|
|
148
|
+
const divide = (numerator, denominator, roundUp) => roundUp ? (numerator + denominator - 1n) / denominator : numerator / denominator;
|
|
149
|
+
// Unsigned on purpose: base-unit fields are u64 values, so a signed string is
|
|
150
|
+
// a malformed response, not a negative amount.
|
|
151
|
+
const parseBaseUnitString = (raw) => {
|
|
152
|
+
if (!/^\d+$/.test(raw))
|
|
153
|
+
return undefined;
|
|
154
|
+
return BigInt(raw);
|
|
155
|
+
};
|
|
156
|
+
//# sourceMappingURL=amount.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"amount.js","sourceRoot":"","sources":["../../../../../../../packages/core/chain/chains/solana/kamino/amount.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { KaminoPnlResponse, KaminoUserPositionResponse, KaminoVaultMetricsResponse, KaminoVaultStateResponse } from './models.js';
|
|
2
|
+
/** Fetches a vault's live state (`GET /kvaults/vaults/{address}`). */
|
|
3
|
+
export declare const fetchKaminoVaultState: (address: string) => Promise<KaminoVaultStateResponse>;
|
|
4
|
+
/** Fetches a vault's metrics (`GET /kvaults/vaults/{address}/metrics`). */
|
|
5
|
+
export declare const fetchKaminoVaultMetrics: (address: string) => Promise<KaminoVaultMetricsResponse>;
|
|
6
|
+
/**
|
|
7
|
+
* Fetches every kVault position the owner holds
|
|
8
|
+
* (`GET /kvaults/users/{owner}/positions`). Uncached and generously timed —
|
|
9
|
+
* this read gates withdraws.
|
|
10
|
+
*/
|
|
11
|
+
export declare const fetchKaminoUserPositions: (owner: string) => Promise<KaminoUserPositionResponse[]>;
|
|
12
|
+
/**
|
|
13
|
+
* Fetches lifetime PnL for one position
|
|
14
|
+
* (`GET /kvaults/users/{owner}/vaults/{vault}/pnl`).
|
|
15
|
+
*/
|
|
16
|
+
export declare const fetchKaminoPnl: ({ owner, vault }: {
|
|
17
|
+
owner: string;
|
|
18
|
+
vault: string;
|
|
19
|
+
}) => Promise<KaminoPnlResponse>;
|
|
20
|
+
//# sourceMappingURL=api.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/chain/chains/solana/kamino/api.ts"],"names":[],"mappings":"AAKA,OAAO,EACL,iBAAiB,EACjB,0BAA0B,EAC1B,0BAA0B,EAC1B,wBAAwB,EACzB,MAAM,UAAU,CAAA;AAyDjB,sEAAsE;AACtE,eAAO,MAAM,qBAAqB,GAAI,SAAS,MAAM,KAAG,OAAO,CAAC,wBAAwB,CACtC,CAAA;AAElD,2EAA2E;AAC3E,eAAO,MAAM,uBAAuB,GAAI,SAAS,MAAM,KAAG,OAAO,CAAC,0BAA0B,CAClC,CAAA;AAE1D;;;;GAIG;AACH,eAAO,MAAM,wBAAwB,GAAI,OAAO,MAAM,KAAG,OAAO,CAAC,0BAA0B,EAAE,CACZ,CAAA;AAEjF;;;GAGG;AACH,eAAO,MAAM,cAAc,GAAI,kBAAkB;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,KAAG,OAAO,CAAC,iBAAiB,CACjC,CAAA"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { HttpResponseError } from '@vultisig/lib-utils/fetch/HttpResponseError';
|
|
2
|
+
import { queryUrl } from '@vultisig/lib-utils/query/queryUrl';
|
|
3
|
+
import { kaminoConfig } from './config.js';
|
|
4
|
+
import { KaminoServiceError } from './KaminoServiceError.js';
|
|
5
|
+
/**
|
|
6
|
+
* Read-side REST client for Kamino Earn vaults, against
|
|
7
|
+
* `https://api.kamino.finance` (public, unauthenticated).
|
|
8
|
+
*
|
|
9
|
+
* Kamino's structured error body is converted into `KaminoServiceError` so
|
|
10
|
+
* callers can branch on `reason.api.code` (`KVAULT_NOT_FOUND`, …) instead of
|
|
11
|
+
* matching message text. Retries are the caller's concern — the client layers
|
|
12
|
+
* (react-query, CLI) already own retry policy, and `KaminoServiceError.isRetryable`
|
|
13
|
+
* tells them whether one is worth it.
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* Timeout for the position read, which gates withdraws. Getting out of a
|
|
17
|
+
* position is the operation whose failure a user cannot route around, so it
|
|
18
|
+
* keeps a long limit: cutting the wait converts "slow" into "cannot withdraw"
|
|
19
|
+
* rather than into a faster answer. Everything else uses `queryUrl`'s 20s
|
|
20
|
+
* default, which no healthy Kamino call approaches (reads measure ~100ms).
|
|
21
|
+
*/
|
|
22
|
+
const positionsReadTimeoutMs = 60_000;
|
|
23
|
+
const isKaminoErrorBody = (body) => typeof body === 'object' &&
|
|
24
|
+
body !== null &&
|
|
25
|
+
typeof body.statusCode === 'number' &&
|
|
26
|
+
typeof body.message === 'string';
|
|
27
|
+
const kaminoGet = async (path, timeoutMs) => {
|
|
28
|
+
try {
|
|
29
|
+
return await queryUrl(`${kaminoConfig.apiBaseUrl}${path}`, timeoutMs === undefined ? undefined : { timeoutMs });
|
|
30
|
+
}
|
|
31
|
+
catch (error) {
|
|
32
|
+
if (error instanceof HttpResponseError && isKaminoErrorBody(error.body)) {
|
|
33
|
+
throw new KaminoServiceError({
|
|
34
|
+
api: { status: error.status, code: error.body.code, message: error.body.message },
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
throw error;
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
// Path parameters are encoded because nothing in this module enforces that
|
|
41
|
+
// they are pubkeys: a value containing `/`, `?` or `#` would otherwise change
|
|
42
|
+
// which endpoint is called. A base58 string passes through unchanged.
|
|
43
|
+
const segment = encodeURIComponent;
|
|
44
|
+
/** Fetches a vault's live state (`GET /kvaults/vaults/{address}`). */
|
|
45
|
+
export const fetchKaminoVaultState = (address) => kaminoGet(`/kvaults/vaults/${segment(address)}`);
|
|
46
|
+
/** Fetches a vault's metrics (`GET /kvaults/vaults/{address}/metrics`). */
|
|
47
|
+
export const fetchKaminoVaultMetrics = (address) => kaminoGet(`/kvaults/vaults/${segment(address)}/metrics`);
|
|
48
|
+
/**
|
|
49
|
+
* Fetches every kVault position the owner holds
|
|
50
|
+
* (`GET /kvaults/users/{owner}/positions`). Uncached and generously timed —
|
|
51
|
+
* this read gates withdraws.
|
|
52
|
+
*/
|
|
53
|
+
export const fetchKaminoUserPositions = (owner) => kaminoGet(`/kvaults/users/${segment(owner)}/positions`, positionsReadTimeoutMs);
|
|
54
|
+
/**
|
|
55
|
+
* Fetches lifetime PnL for one position
|
|
56
|
+
* (`GET /kvaults/users/{owner}/vaults/{vault}/pnl`).
|
|
57
|
+
*/
|
|
58
|
+
export const fetchKaminoPnl = ({ owner, vault }) => kaminoGet(`/kvaults/users/${segment(owner)}/vaults/${segment(vault)}/pnl`);
|
|
59
|
+
//# sourceMappingURL=api.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api.js","sourceRoot":"","sources":["../../../../../../../packages/core/chain/chains/solana/kamino/api.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,6CAA6C,CAAA;AAC/E,OAAO,EAAE,QAAQ,EAAE,MAAM,oCAAoC,CAAA;AAE7D,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAA;AACvC,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAA;AAQzD;;;;;;;;;GASG;AAEH;;;;;;GAMG;AACH,MAAM,sBAAsB,GAAG,MAAM,CAAA;AAarC,MAAM,iBAAiB,GAAG,CAAC,IAAa,EAA+B,EAAE,CACvE,OAAO,IAAI,KAAK,QAAQ;IACxB,IAAI,KAAK,IAAI;IACb,OAAQ,IAA4B,CAAC,UAAU,KAAK,QAAQ;IAC5D,OAAQ,IAA4B,CAAC,OAAO,KAAK,QAAQ,CAAA;AAE3D,MAAM,SAAS,GAAG,KAAK,EAAK,IAAY,EAAE,SAAkB,EAAc,EAAE;IAC1E,IAAI,CAAC;QACH,OAAO,MAAM,QAAQ,CAAI,GAAG,YAAY,CAAC,UAAU,GAAG,IAAI,EAAE,EAAE,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,CAAA;IACpH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,iBAAiB,IAAI,iBAAiB,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;YACxE,MAAM,IAAI,kBAAkB,CAAC;gBAC3B,GAAG,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE;aAClF,CAAC,CAAA;QACJ,CAAC;QACD,MAAM,KAAK,CAAA;IACb,CAAC;AACH,CAAC,CAAA;AAED,2EAA2E;AAC3E,8EAA8E;AAC9E,sEAAsE;AACtE,MAAM,OAAO,GAAG,kBAAkB,CAAA;AAElC,sEAAsE;AACtE,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,OAAe,EAAqC,EAAE,CAC1F,SAAS,CAAC,mBAAmB,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,CAAA;AAElD,2EAA2E;AAC3E,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,OAAe,EAAuC,EAAE,CAC9F,SAAS,CAAC,mBAAmB,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,CAAA;AAE1D;;;;GAIG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,KAAa,EAAyC,EAAE,CAC/F,SAAS,CAAC,kBAAkB,OAAO,CAAC,KAAK,CAAC,YAAY,EAAE,sBAAsB,CAAC,CAAA;AAEjF;;;GAGG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,EAAE,KAAK,EAAE,KAAK,EAAoC,EAA8B,EAAE,CAC/G,SAAS,CAAC,kBAAkB,OAAO,CAAC,KAAK,CAAC,WAAW,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,CAAA"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rendering and bounds shared by the Kamino amount types.
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Solana instruction arguments are `u64`; anything above that cannot be
|
|
6
|
+
* expressed on-chain regardless of what the API would accept.
|
|
7
|
+
*/
|
|
8
|
+
export declare const kaminoMaxBaseUnits: bigint;
|
|
9
|
+
/**
|
|
10
|
+
* Widest decimal scale we are willing to handle. SPL mints are a `u8`, but
|
|
11
|
+
* nothing legitimate approaches this, and an absurd scale would make the
|
|
12
|
+
* `10^decimals` factors in the conversions unbounded.
|
|
13
|
+
*/
|
|
14
|
+
export declare const kaminoMaxDecimals = 18;
|
|
15
|
+
/**
|
|
16
|
+
* Renders base units as a plain human-units decimal string: no grouping, no
|
|
17
|
+
* trailing zeros, no exponent. This is the form Kamino's request bodies take.
|
|
18
|
+
*/
|
|
19
|
+
export declare const renderKaminoBaseUnits: ({ baseUnits, decimals }: {
|
|
20
|
+
baseUnits: bigint;
|
|
21
|
+
decimals: number;
|
|
22
|
+
}) => string;
|
|
23
|
+
//# sourceMappingURL=baseUnits.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"baseUnits.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/chain/chains/solana/kamino/baseUnits.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;GAGG;AACH,eAAO,MAAM,kBAAkB,QAAiB,CAAA;AAEhD;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,KAAK,CAAA;AAEnC;;;GAGG;AACH,eAAO,MAAM,qBAAqB,GAAI,yBAAyB;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,KAAG,MAWxG,CAAA"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rendering and bounds shared by the Kamino amount types.
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Solana instruction arguments are `u64`; anything above that cannot be
|
|
6
|
+
* expressed on-chain regardless of what the API would accept.
|
|
7
|
+
*/
|
|
8
|
+
export const kaminoMaxBaseUnits = 2n ** 64n - 1n;
|
|
9
|
+
/**
|
|
10
|
+
* Widest decimal scale we are willing to handle. SPL mints are a `u8`, but
|
|
11
|
+
* nothing legitimate approaches this, and an absurd scale would make the
|
|
12
|
+
* `10^decimals` factors in the conversions unbounded.
|
|
13
|
+
*/
|
|
14
|
+
export const kaminoMaxDecimals = 18;
|
|
15
|
+
/**
|
|
16
|
+
* Renders base units as a plain human-units decimal string: no grouping, no
|
|
17
|
+
* trailing zeros, no exponent. This is the form Kamino's request bodies take.
|
|
18
|
+
*/
|
|
19
|
+
export const renderKaminoBaseUnits = ({ baseUnits, decimals }) => {
|
|
20
|
+
const isNegative = baseUnits < 0n;
|
|
21
|
+
const digits = (isNegative ? -baseUnits : baseUnits).toString();
|
|
22
|
+
if (decimals <= 0)
|
|
23
|
+
return isNegative ? `-${digits}` : digits;
|
|
24
|
+
const padded = digits.padStart(decimals + 1, '0');
|
|
25
|
+
const whole = padded.slice(0, padded.length - decimals);
|
|
26
|
+
const fraction = padded.slice(padded.length - decimals).replace(/0+$/, '');
|
|
27
|
+
const magnitude = fraction ? `${whole}.${fraction}` : whole;
|
|
28
|
+
return isNegative ? `-${magnitude}` : magnitude;
|
|
29
|
+
};
|
|
30
|
+
//# sourceMappingURL=baseUnits.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"baseUnits.js","sourceRoot":"","sources":["../../../../../../../packages/core/chain/chains/solana/kamino/baseUnits.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;GAGG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,EAAE,IAAI,GAAG,GAAG,EAAE,CAAA;AAEhD;;;;GAIG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,EAAE,CAAA;AAEnC;;;GAGG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,EAAE,SAAS,EAAE,QAAQ,EAA2C,EAAU,EAAE;IAChH,MAAM,UAAU,GAAG,SAAS,GAAG,EAAE,CAAA;IACjC,MAAM,MAAM,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,QAAQ,EAAE,CAAA;IAC/D,IAAI,QAAQ,IAAI,CAAC;QAAE,OAAO,UAAU,CAAC,CAAC,CAAC,IAAI,MAAM,EAAE,CAAC,CAAC,CAAC,MAAM,CAAA;IAE5D,MAAM,MAAM,GAAG,MAAM,CAAC,QAAQ,CAAC,QAAQ,GAAG,CAAC,EAAE,GAAG,CAAC,CAAA;IACjD,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,MAAM,GAAG,QAAQ,CAAC,CAAA;IACvD,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,GAAG,QAAQ,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAA;IAE1E,MAAM,SAAS,GAAG,QAAQ,CAAC,CAAC,CAAC,GAAG,KAAK,IAAI,QAAQ,EAAE,CAAC,CAAC,CAAC,KAAK,CAAA;IAC3D,OAAO,UAAU,CAAC,CAAC,CAAC,IAAI,SAAS,EAAE,CAAC,CAAC,CAAC,SAAS,CAAA;AACjD,CAAC,CAAA"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Constants for Kamino Earn vaults (kVaults) on Solana.
|
|
3
|
+
*
|
|
4
|
+
* The REST API is public and unauthenticated — the action endpoints build an
|
|
5
|
+
* unsigned transaction from the caller's wallet address alone, which is why
|
|
6
|
+
* every built transaction must be validated on-device before it is signed.
|
|
7
|
+
*/
|
|
8
|
+
export declare const kaminoConfig: {
|
|
9
|
+
/** Kamino's public REST API. No key, no auth header. */
|
|
10
|
+
readonly apiBaseUrl: "https://api.kamino.finance";
|
|
11
|
+
/** The kVaults program every deposit and withdraw invokes. */
|
|
12
|
+
readonly programId: "KvauGMspG5k6rtzrqqn7WNn3oZdyKqLKwK2XWQ8FLjd";
|
|
13
|
+
/**
|
|
14
|
+
* Kamino's farms program. Every launch vault has a farm attached, so a
|
|
15
|
+
* deposit ends with `initializeUser` + `stake` against this program and the
|
|
16
|
+
* shares never land in the user's wallet.
|
|
17
|
+
*/
|
|
18
|
+
readonly farmsProgramId: "FarmsPZpWu9i7Kky8tPN37rs2TpmMrAZrC7S7vJa91Hr";
|
|
19
|
+
/**
|
|
20
|
+
* Wrapped SOL. The SOL vault's underlying token is this mint, not native
|
|
21
|
+
* SOL, which is why its deposits carry a wrap prefix.
|
|
22
|
+
*/
|
|
23
|
+
readonly wrappedSolMint: "So11111111111111111111111111111111111111112";
|
|
24
|
+
/** Circle's USDC — the underlying token of both dollar vaults. */
|
|
25
|
+
readonly usdcMint: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v";
|
|
26
|
+
};
|
|
27
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/chain/chains/solana/kamino/config.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,eAAO,MAAM,YAAY;IACvB,wDAAwD;;IAGxD,8DAA8D;;IAG9D;;;;OAIG;;IAGH;;;OAGG;;IAGH,kEAAkE;;CAE1D,CAAA"}
|