@subly_fi/pay 0.6.1 → 0.7.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/dist/vaults.js ADDED
@@ -0,0 +1,129 @@
1
+ // ../../src/config/vault-catalog.ts
2
+ import { readFileSync } from "node:fs";
3
+ import { z } from "zod";
4
+
5
+ // ../../src/lib/solana-address.ts
6
+ var BASE58_ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
7
+ var BASE58_LOOKUP = new Map(
8
+ [...BASE58_ALPHABET].map((character, index) => [character, BigInt(index)])
9
+ );
10
+ function assertSolanaAddress(value, fieldName) {
11
+ if (value.length < 32 || value.length > 44) {
12
+ throw new Error(`${fieldName} must be a valid Solana public key`);
13
+ }
14
+ if (decodeBase58(value).length !== 32) {
15
+ throw new Error(`${fieldName} must be a valid Solana public key`);
16
+ }
17
+ return value;
18
+ }
19
+ function decodeBase58(value) {
20
+ if (value.length === 0) {
21
+ return new Uint8Array();
22
+ }
23
+ let decoded = 0n;
24
+ for (const character of value) {
25
+ const digit = BASE58_LOOKUP.get(character);
26
+ if (digit === void 0) {
27
+ return new Uint8Array();
28
+ }
29
+ decoded = decoded * 58n + digit;
30
+ }
31
+ const bytes = [];
32
+ while (decoded > 0n) {
33
+ bytes.push(Number(decoded & 0xffn));
34
+ decoded >>= 8n;
35
+ }
36
+ for (const character of value) {
37
+ if (character !== "1") {
38
+ break;
39
+ }
40
+ bytes.push(0);
41
+ }
42
+ return Uint8Array.from(bytes.reverse());
43
+ }
44
+
45
+ // ../../src/config/vault.ts
46
+ var MAINNET_USDC_MINT = "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v";
47
+ var KAMINO_VAULT_PROGRAM_ID = "KvauGMspG5k6rtzrqqn7WNn3oZdyKqLKwK2XWQ8FLjd";
48
+ var NO_VAULT_FARM = "11111111111111111111111111111111";
49
+ var DEFAULT_VAULT_CONFIG = Object.freeze({
50
+ address: "5kfkpQZ6AkQgizHVThqkxD4J3db2i7pE3mHdPNRbx7jr",
51
+ programId: KAMINO_VAULT_PROGRAM_ID,
52
+ usdcMint: MAINNET_USDC_MINT,
53
+ shareMint: "7hGX49So539MU9Rrah8nBNVYXswWVwEJvgWNYeBDYq3a",
54
+ farm: "E2Ct77LowkDAH1T9ubwPpb84pU2GSGrUdgH3KeTTpLX"
55
+ });
56
+ function vaultConfigFromEnv(env = process.env) {
57
+ const value = (name) => env[name]?.trim() || void 0;
58
+ const vaultAddress = value("SUBLY_VAULT_ADDRESS") ?? DEFAULT_VAULT_CONFIG.address;
59
+ const customVault = vaultAddress !== DEFAULT_VAULT_CONFIG.address;
60
+ const anchor = (name, fallback) => {
61
+ const configured = value(name);
62
+ if (customVault && configured === void 0) {
63
+ throw new Error(
64
+ `${name} is required for a custom vault. Generate its settings with npm run configure:vault -- <vault-address>; use ${NO_VAULT_FARM} for a vault without a farm.`
65
+ );
66
+ }
67
+ return assertSolanaAddress(configured ?? fallback, name);
68
+ };
69
+ const usdcMint = value("SUBLY_VAULT_USDC_MINT") ?? MAINNET_USDC_MINT;
70
+ if (usdcMint !== MAINNET_USDC_MINT) {
71
+ throw new Error(
72
+ "SUBLY_VAULT_USDC_MINT must be mainnet USDC; other deposit assets are not supported"
73
+ );
74
+ }
75
+ return Object.freeze({
76
+ address: assertSolanaAddress(vaultAddress, "SUBLY_VAULT_ADDRESS"),
77
+ programId: KAMINO_VAULT_PROGRAM_ID,
78
+ usdcMint,
79
+ shareMint: anchor("SUBLY_VAULT_SHARE_MINT", DEFAULT_VAULT_CONFIG.shareMint),
80
+ farm: anchor("SUBLY_VAULT_FARM", DEFAULT_VAULT_CONFIG.farm)
81
+ });
82
+ }
83
+
84
+ // ../../src/config/vault-catalog.ts
85
+ var publicKey = z.string().refine((value) => {
86
+ try {
87
+ assertSolanaAddress(value, "vault catalog address");
88
+ return true;
89
+ } catch {
90
+ return false;
91
+ }
92
+ }, "Invalid Solana public key");
93
+ var catalogSchema = z.object({
94
+ version: z.literal(1),
95
+ defaultVault: publicKey,
96
+ vaults: z.array(z.object({
97
+ address: publicKey,
98
+ programId: z.literal(KAMINO_VAULT_PROGRAM_ID),
99
+ usdcMint: z.literal(MAINNET_USDC_MINT),
100
+ shareMint: publicKey,
101
+ farm: publicKey,
102
+ name: z.string().min(1).max(128).optional(),
103
+ depositsEnabled: z.boolean().optional(),
104
+ extraLookupTables: z.array(publicKey).max(16).optional()
105
+ }).strict()).min(1).max(100)
106
+ }).strict();
107
+ function parseVaultCatalog(value) {
108
+ const catalog = catalogSchema.parse(value);
109
+ const addresses = new Set(catalog.vaults.map((vault) => vault.address));
110
+ if (addresses.size !== catalog.vaults.length) throw new Error("Duplicate vault in catalog");
111
+ if (!addresses.has(catalog.defaultVault)) throw new Error("defaultVault must be in the vault catalog");
112
+ return { ...catalog, vaults: catalog.vaults.map((vault) => Object.freeze(vault)) };
113
+ }
114
+ function vaultCatalogFromEnv(env = process.env) {
115
+ const path = env.SUBLY_VAULTS_FILE?.trim();
116
+ if (!path) {
117
+ const vault = vaultConfigFromEnv(env);
118
+ return { version: 1, defaultVault: vault.address, vaults: [vault] };
119
+ }
120
+ const catalog = parseVaultCatalog(JSON.parse(readFileSync(path, "utf8")));
121
+ const selected = env.SUBLY_VAULT_ADDRESS?.trim() || catalog.defaultVault;
122
+ if (!catalog.vaults.some((vault) => vault.address === selected)) {
123
+ throw new Error("SUBLY_VAULT_ADDRESS must be in SUBLY_VAULTS_FILE");
124
+ }
125
+ return { ...catalog, defaultVault: selected };
126
+ }
127
+
128
+ // src/vaults.ts
129
+ console.log(JSON.stringify(vaultCatalogFromEnv(), null, 2));