{"_id":"@avodotso/market-sdk","_rev":"3-083cbec75d0b9c67a91302b5ce1fc80d","name":"@avodotso/market-sdk","dist-tags":{"latest":"0.1.5"},"versions":{"0.1.0":{"name":"@avodotso/market-sdk","version":"0.1.0","keywords":["solana","avo-portfolio","market-maker","rebalance","nav","sdk","client"],"license":"ISC","_id":"@avodotso/market-sdk@0.1.0","maintainers":[{"name":"morgandri1dev","email":"morgan@avo.so"}],"homepage":"https://github.com/avodotso/market-sdk#readme","bugs":{"url":"https://github.com/avodotso/market-sdk/issues"},"dist":{"shasum":"970d62650c467cc007b21c87d20e4caba2d350b9","tarball":"https://registry.npmjs.org/@avodotso/market-sdk/-/market-sdk-0.1.0.tgz","fileCount":31,"integrity":"sha512-HJVN9lQeaZR0o44770uocQJ/VjTLC4/vhXqjViTfJTeHjoyx/ZeLbrDf5OlIkm55UeoNo6/8P8NtLihuHxIhLg==","signatures":[{"sig":"MEYCIQCRu6PFjgJpMzRVRVGeFRcX81Owz3wVGca0wNlRl5Z6xQIhAPW7h4m6fAiO6Hsg6hGkqpN8X0NGL4GnSN+IeK6HKPoT","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":93785},"main":"dist/index.js","types":"dist/index.d.ts","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./package.json":"./package.json"},"gitHead":"6cc6e2acb83d095f6d2e860f4237c3b2a3f17208","scripts":{"test":"vitest run","build":"tsc","clean":"rm -rf dist","test:watch":"vitest","prepublishOnly":"yarn clean && yarn build && yarn test"},"_npmUser":{"name":"morgandri1dev","email":"morgan@avo.so"},"repository":{"url":"git+https://github.com/avodotso/market-sdk.git","type":"git"},"_npmVersion":"10.8.2","description":"TypeScript client for the Avo Portfolio API. Bootstrap a market-maker agent, run rebalances, push NAV updates — custodial or self-custodial.","directories":{},"_nodeVersion":"20.20.2","dependencies":{"bs58":"^6.0.0","tweetnacl":"^1.0.3"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^2.1.9","typescript":"^5.7.3","@types/node":"^20.0.0"},"_npmOperationalInternal":{"tmp":"tmp/market-sdk_0.1.0_1781751167859_0.11535687348027368","host":"s3://npm-registry-packages-npm-production"}},"0.1.2":{"name":"@avodotso/market-sdk","version":"0.1.2","keywords":["solana","avo-portfolio","market-maker","rebalance","nav","sdk","client"],"license":"ISC","_id":"@avodotso/market-sdk@0.1.2","maintainers":[{"name":"morgandri1dev","email":"morgan@avo.so"}],"homepage":"https://github.com/avodotso/market-sdk#readme","bugs":{"url":"https://github.com/avodotso/market-sdk/issues"},"dist":{"shasum":"e1474ee6cbe635d152fafc4adc6f78407e5b6875","tarball":"https://registry.npmjs.org/@avodotso/market-sdk/-/market-sdk-0.1.2.tgz","fileCount":31,"integrity":"sha512-QuuiDHJVxQnl0u/KuzSBxE63GxNTzOoYg4tyIZ2EAymBFWFHyFa0jV0BBgsy1YczLWxNh2gcj9zu4UjdMrOp7A==","signatures":[{"sig":"MEUCIEH7fXD1w5hBbqNU9q42pAnmdMG6xuYn5VweXuR6I7hGAiEA1wtNEXWIk1fwFppxMaKaKKE9pMznZte+QWWMXYwyb2s=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":98616},"main":"dist/index.js","types":"dist/index.d.ts","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./package.json":"./package.json"},"gitHead":"61985e1e5447a0ea71561d3f3bd2c1c4630317de","scripts":{"test":"vitest run","build":"tsc","clean":"rm -rf dist","test:watch":"vitest","prepublishOnly":"yarn clean && yarn build && yarn test"},"_npmUser":{"name":"morgandri1dev","email":"morgan@avo.so"},"repository":{"url":"git+https://github.com/avodotso/market-sdk.git","type":"git"},"_npmVersion":"10.8.2","description":"TypeScript client for the Avo Portfolio API. Bootstrap a market-maker agent, run rebalances, push NAV updates — custodial or self-custodial.","directories":{},"_nodeVersion":"20.20.2","dependencies":{"bs58":"^6.0.0","tweetnacl":"^1.0.3"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^2.1.9","typescript":"^5.7.3","@types/node":"^20.0.0"},"_npmOperationalInternal":{"tmp":"tmp/market-sdk_0.1.2_1783308240021_0.544136166244253","host":"s3://npm-registry-packages-npm-production"}},"0.1.5":{"name":"@avodotso/market-sdk","version":"0.1.5","description":"TypeScript client for the Avo Portfolio API. Bootstrap a market-maker agent, run rebalances, push NAV updates — custodial or self-custodial.","main":"dist/index.js","types":"dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./package.json":"./package.json"},"scripts":{"build":"tsc","clean":"rm -rf dist","test":"vitest run","test:watch":"vitest","prepublishOnly":"yarn clean && yarn build && yarn test"},"keywords":["solana","avo-portfolio","market-maker","rebalance","nav","sdk","client"],"repository":{"type":"git","url":"git+https://github.com/avodotso/market-sdk.git"},"bugs":{"url":"https://github.com/avodotso/market-sdk/issues"},"homepage":"https://github.com/avodotso/market-sdk#readme","license":"ISC","publishConfig":{"registry":"https://registry.npmjs.org","access":"public"},"engines":{"node":">=18"},"dependencies":{"bs58":"^6.0.0","tweetnacl":"^1.0.3"},"devDependencies":{"@types/node":"^20.0.0","typescript":"^5.7.3","vitest":"^2.1.9"},"_id":"@avodotso/market-sdk@0.1.5","gitHead":"73071f39a11537018f214988cf9e36053079f865","_nodeVersion":"20.20.2","_npmVersion":"10.8.2","dist":{"integrity":"sha512-UymtraZW28ZdCLGSk6iSsHrHtfNCPTjPW6TM0LEAO2GpLdSubnTWzPesZr2vElrqupwPs6/Dl7gLmGDBpeUYXA==","shasum":"98e2b727cee7c7bc759dad07a8a5e8526744b4e6","tarball":"https://registry.npmjs.org/@avodotso/market-sdk/-/market-sdk-0.1.5.tgz","fileCount":31,"unpackedSize":99175,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIEGvVBNSh9W0BL27HhAfYkig1+xFX1T92FrXsYfTEKwcAiBlhVUiqZ5nwV+hJjm55FmxDRZDX7gZOWf8pRL9PxZfyg=="}]},"_npmUser":{"name":"morgandri1dev","email":"morgan@avo.so"},"directories":{},"maintainers":[{"name":"morgandri1dev","email":"morgan@avo.so"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/market-sdk_0.1.5_1783309751442_0.12235531207113404"},"_hasShrinkwrap":false}},"time":{"created":"2026-06-18T02:52:47.760Z","modified":"2026-07-06T03:49:11.726Z","0.1.0":"2026-06-18T02:52:48.044Z","0.1.2":"2026-07-06T03:24:00.151Z","0.1.5":"2026-07-06T03:49:11.599Z"},"bugs":{"url":"https://github.com/avodotso/market-sdk/issues"},"license":"ISC","homepage":"https://github.com/avodotso/market-sdk#readme","keywords":["solana","avo-portfolio","market-maker","rebalance","nav","sdk","client"],"repository":{"type":"git","url":"git+https://github.com/avodotso/market-sdk.git"},"description":"TypeScript client for the Avo Portfolio API. Bootstrap a market-maker agent, run rebalances, push NAV updates — custodial or self-custodial.","maintainers":[{"name":"morgandri1dev","email":"morgan@avo.so"}],"readme":"# `@avodotso/market-sdk`\n\nTypeScript client for the [Avo Portfolio](https://avo.so) API on Solana. Built for market-makers: bootstrap an agent, run rebalances, push NAV updates — over plain HTTP, with one client class.\n\n```bash\nnpm install @avodotso/market-sdk\n# or\nyarn add @avodotso/market-sdk\n```\n\nThe SDK exports one primary class — `MarketClient` — that covers the entire market-maker journey: create → operate → close. No internal-only services, no chain-side ix builders, just the public HTTP API.\n\n---\n\n## Quickstart\n\n### Operate a market (custodial — recommended)\n\nYou hold a bearer token (returned from `finalizeCreateMarket` or `registerMarket`); the API holds the agent's signing keypair encrypted at rest. **You never touch a private key.**\n\n```ts\nimport { MarketClient } from '@avodotso/market-sdk';\n\nconst client = new MarketClient({\n  services: { avoApi: 'https://portfolio-contract-api-service-dev.up.railway.app' },\n  agent: { bearer: process.env.AGENT_BEARER! },\n});\n\n// Live valuation of every vault in the market.\nconst value = await client.getValue(/* slippageBps = */ 50);\n\n// Rebalance to a new target weight vector (asset mint → percent; sum = 100).\nawait client.rebalance({\n  weights: [\n    { asset: 'base', weight: 0 },\n    { asset: 'So11111111111111111111111111111111111111112', weight: 50 },\n    { asset: 'DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263', weight: 50 },\n  ],\n  slippageBps: 100,\n  deadlineSecs: 180,\n});\n\n// Push fresh NAV onto chain.\nawait client.updateNav();\n```\n\n### Operate a market (self-custodial — Sig auth)\n\nYou hold the agent's 64-byte Ed25519 secret key yourself; the SDK mints fresh signed tokens on every call window.\n\n```ts\nimport { MarketClient } from '@avodotso/market-sdk';\nimport { Keypair } from '@solana/web3.js';\n\nconst agentKp = Keypair.fromSecretKey(/* your agent's 64-byte secret key */);\n\nconst client = new MarketClient({\n  services: { avoApi: 'https://portfolio-contract-api-service-dev.up.railway.app' },\n  agent: {\n    publicKey: agentKp.publicKey.toBytes(),\n    secretKey: agentKp.secretKey,\n  },\n});\n\nawait client.rebalance({ /* ... */ });\n```\n\nExternal signers (KMS / hardware wallet / Turnkey) are supported via `agent.signer` — see [Auth model](#auth-model) below.\n\n### Create a new market (permissionless flow)\n\nThe API generates a fresh agent keypair custodially. You sign the funding tx with your operator wallet; the API does the rest. You get back a one-time bearer for ongoing ops.\n\n```ts\nimport { MarketClient } from '@avodotso/market-sdk';\nimport { VersionedTransaction } from '@solana/web3.js';\n\nconst client = new MarketClient({ services: { avoApi: 'https://portfolio-contract-api-service-dev.up.railway.app' } });\n\n// Phase 1: register intent + receive an unsigned 0.1 SOL funding tx.\nconst prep = await client.prepareCreateMarket({\n  creator: myWallet.publicKey.toBase58(),\n  baseAssetMint: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v', // USDC mainnet\n  feeAssetMint: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',\n  marketFeeBps: 30,\n  label: 'My Index',\n  assetMints: ['So11111111111111111111111111111111111111112'],\n  initialWeights: { base: 0, So11111111111111111111111111111111111111112: 10_000 },\n});\n\n// Phase 1b: your wallet signs + submits the funding transfer.\nconst tx = VersionedTransaction.deserialize(Buffer.from(prep.fundingTx, 'base64'));\nconst fundingSig = await myWallet.signAndSendTransaction(tx);\n\n// Phase 2: API verifies funding, custodial agent signs `create_market`\n// on chain, weight-set rebalance lands the initial weights atomically.\nconst result = await client.finalizeCreateMarket({\n  agentPubkey: prep.agentPubkey,\n  fundingSignature: fundingSig,\n});\n\nconsole.log({\n  marketPda: result.marketPda,\n  agentPubkey: result.agentPubkey,\n  bearer: result.bearer, // STORE NOW — shown ONCE\n});\n```\n\n### Register a market you built on-chain yourself\n\nYou generated the agent keypair locally, built + submitted `create_market` on chain via Anchor, and want the API to hold the keypair for custodial signing of subsequent ops. The API validates the secret matches the on-chain `Market.agent` before encrypting + storing.\n\n```ts\nimport bs58 from 'bs58';\n\nconst result = await client.registerMarket({\n  marketPda: myMarketPda.toBase58(),\n  agentSecretBase58: bs58.encode(agentKp.secretKey),\n  label: 'My Self-Custody Market',\n});\n// Same shape: one-time bearer for the custodial path going forward.\n```\n\n---\n\n## Method reference\n\n### Bootstrap (no auth)\n\n| Method | Endpoint | Notes |\n|---|---|---|\n| `prepareCreateMarket(body)` | `POST /v1/markets/create/prepare` | Returns an unsigned funding tx. |\n| `finalizeCreateMarket(body)` | `POST /v1/markets/create/finalize` | Returns marketPda + one-time bearer. |\n| `registerMarket(body)` | `POST /v1/markets/register` | For markets you created on chain yourself. |\n\n### Public reads (no auth)\n\n| Method | Endpoint | Notes |\n|---|---|---|\n| `healthz()` | `GET /healthz` | API liveness. |\n| `listMarkets({ limit, offset })` | `GET /v1/markets` | Paginated catalog. |\n| `getMarketEvents(pda, { limit, before })` | `GET /v1/markets/{pda}/events` | On-chain activity log; paged via `before` cursor. |\n| `getNavHistory(pda, { limit, order, from, to })` | `GET /v1/markets/{pda}/nav-history` | NAV time series. `from`/`to` accept `Date` or ISO string. |\n| `getIdentity(agentPubkey)` | `GET /v1/agents/identity/{pubkey}` | MPL-8004 identity + reputation. |\n| `attachIdentity(body)` | `POST /v1/agents/identity/attach` | Attach a Core NFT identity (signature-gated, permissionless). |\n\n### Agent ops (authenticated — requires `agent` in constructor)\n\n| Method | Endpoint | Notes |\n|---|---|---|\n| `getMarket()` | `GET /v1/market` | The configured agent's market. |\n| `getAssets()` | `GET /v1/assets` | Registered MarketAssets. |\n| `getValue(slippageBps?)` | `GET /v1/value` | Live NAV via Jupiter quotes. |\n| `getQuote(params)` | `GET /v1/quote` | Jupiter quote passthrough. |\n| `updateNav(body?)` | `POST /v1/nav` | Push fresh `last_total_value`. |\n| `rebalance(body)` | `POST /v1/rebalance` | Custodial prepare → leg × N → settle. |\n| `simulateRebalance(body)` | `POST /v1/rebalance/simulate` | Dry-run. |\n| `addAsset(body)` | `POST /v1/assets` | Register a MarketAsset at 0% weight. |\n| `removeAsset(mint, opts?)` | `DELETE /v1/assets/{mint}` | Liquidate + close the vault. |\n| `getOwnIdentity()` | `GET /v1/agents/identity/{self}` | Self-lookup wrapper. |\n\n---\n\n## Auth model\n\n`MarketClient` agent-op methods support two auth modes. **Both produce identical access to the same agent identity** — they just differ in where the signing material lives.\n\n### Bearer (custodial)\n\nThe agent's secret key stays encrypted inside the API. You only hold the one-time bearer returned by `finalizeCreateMarket` / `registerMarket`. **Recommended default** for hosted market-makers — no key management on your side, and the bearer is a single short string you can rotate by re-registering the market.\n\n```ts\nnew MarketClient({\n  services: { avoApi: 'https://portfolio-contract-api-service-dev.up.railway.app' },\n  agent: {\n    bearer: 'mb_8e3f…',                // stored from finalizeCreateMarket\n    publicKey: kp.publicKey.toBytes(), // optional; enables getOwnIdentity()\n  },\n});\n```\n\nStamps `Authorization: Bearer <token>` on every agent-op call. The API hashes the token at receipt (`sha256`) and matches it against the `bearerHash` it stored at registration. No TTL — valid until you rotate or get the agent revoked.\n\n**Threat model.** A leaked bearer is equivalent operational power to a leaked secret key *against the API*: the attacker can rebalance / update NAV / add or remove assets as your agent. But the blast radius is bounded relative to the keypair:\n\n- The bearer **cannot sign on-chain transactions outside our API** — it's not a Solana keypair.\n- The bearer **cannot withdraw the agent's keypair** — that material never leaves the API's at-rest encryption.\n- Rotation is one HTTP call: re-register the same market.\n\n### Sig (self-custodial)\n\nYou hold the Ed25519 secret key yourself; the SDK mints a short-lived signed token over a canonical message:\n\n```\navo-portfolio-api/v1\n<agent pubkey base58>\n<expiresAt unix milliseconds>\n```\n\nIn-process secret:\n\n```ts\nnew MarketClient({\n  agent: {\n    publicKey: kp.publicKey.toBytes(),\n    secretKey: kp.secretKey,\n  },\n});\n```\n\nExternal signer (KMS / hardware wallet / Turnkey):\n\n```ts\nnew MarketClient({\n  agent: {\n    publicKey: kp.publicKey.toBytes(),\n    signer: async (message: Uint8Array) => {\n      return await myExternalSigner.sign(message); // returns 64-byte Ed25519 sig\n    },\n  },\n});\n```\n\nTokens are minted lazily and cached until ~30 s before expiry. TTL defaults to **600 s** (10 min); override with `tokenTtlSecs` on the constructor. The API caps TTL at its own `MAX_AUTH_TTL_SECS`, so over-long TTLs are clamped server-side.\n\nFor minting tokens outside the SDK (e.g. server-side verifying its own auth):\n\n```ts\nimport { canonicalAuthMessage, mintAuthToken } from '@avodotso/market-sdk';\n\nconst { token, expiresAtMs } = await mintAuthToken({\n  publicKey: kp.publicKey.toBytes(),\n  secretKey: kp.secretKey,\n}, /* ttlSecs = */ 600);\n```\n\n### Picking between them\n\n- **Just did `prepareCreateMarket` + `finalizeCreateMarket`?** Use bearer — you don't have the keypair (the API does).\n- **Built your market on-chain yourself + called `registerMarket`?** Either works. Sig is more self-custodial; bearer is simpler.\n- **Operating someone else's market on their behalf?** Whichever credential they handed you. Bearers are easier to scope-down and rotate.\n\n---\n\n## Config\n\n`MarketClient` reads the API base URL from `AvoServiceConfig`. Just one slot:\n\n```ts\nimport { resolveServiceConfig } from '@avodotso/market-sdk';\n\nconst services = resolveServiceConfig({\n  avoApi: 'https://portfolio-contract-api-service-dev.up.railway.app',\n});\n\nconst client = new MarketClient({ services });\n```\n\nYou can pass a custom `fetch` for testing or instrumentation:\n\n```ts\nnew MarketClient({\n  services: { avoApi: 'https://portfolio-contract-api-service-dev.up.railway.app' },\n  fetch: myInstrumentedFetch,\n});\n```\n\n---\n\n## Errors\n\nEvery HTTP failure throws `AvoSdkError`. Network failures (DNS / connection refused / non-JSON body) throw `AvoTransportError`.\n\n```ts\nimport { AvoSdkError, AvoTransportError } from '@avodotso/market-sdk';\n\ntry {\n  await client.rebalance({ /* ... */ });\n} catch (err) {\n  if (err instanceof AvoSdkError) {\n    console.error(err.status, err.code, err.message, err.details);\n  } else if (err instanceof AvoTransportError) {\n    console.error('network failure:', err.message);\n  } else {\n    throw err;\n  }\n}\n```\n\n`AvoSdkError` codes the SDK itself raises:\n\n| Code | When |\n|---|---|\n| `SERVICE_UNCONFIGURED` | No `services.avoApi` was set. |\n| `AGENT_NOT_CONFIGURED` | A protected method was called on an unauthenticated client (or `getOwnIdentity` in bearer mode without `publicKey`). |\n| `AGENT_AUTH_AMBIGUOUS` | Constructor got both signer credentials and a bearer. |\n| `AGENT_PUBLIC_KEY_MISSING` | Sig mode constructor without `publicKey`. |\n| `AGENT_AUTH_EMPTY` | Constructor got `agent: {}` with no auth material. |\n| `HTTP_<status>` | API returned a non-2xx with no parseable error envelope. |\n\nAll other `code` values come straight from the API's error envelope.\n\n---\n\n## Versioning\n\nSemver. Anything documented above is stable.\n\n## License\n\nISC. See `LICENSE`.\n","readmeFilename":"README.md"}