From ea2d033fde66f1fe6874a209b5d82e44e6c6c206 Mon Sep 17 00:00:00 2001 From: Danswar <48102227+Danswar@users.noreply.github.com> Date: Wed, 26 Nov 2025 16:36:22 -0300 Subject: [PATCH 1/8] Contract v1.0.2 (#2) --- package.json | 4 ++-- yarn.lock | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index b9100b0..b12c714 100644 --- a/package.json +++ b/package.json @@ -32,7 +32,7 @@ }, "dependencies": { "@apollo/client": "^3.10.5", - "@juicedollar/jusd": "^1.0.1", + "@juicedollar/jusd": "^1.0.2", "@nestjs/common": "^10.0.0", "@nestjs/config": "^3.2.3", "@nestjs/core": "^10.0.0", @@ -94,4 +94,4 @@ "coverageDirectory": "../coverage", "testEnvironment": "node" } -} \ No newline at end of file +} diff --git a/yarn.lock b/yarn.lock index 9b1ec5a..51419b4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -902,10 +902,10 @@ "@jridgewell/resolve-uri" "^3.1.0" "@jridgewell/sourcemap-codec" "^1.4.14" -"@juicedollar/jusd@^1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@juicedollar/jusd/-/jusd-1.0.1.tgz#b9cd0787bd98a49c2238f0a2cb175ebb54f5cd5f" - integrity sha512-giqtQtwn+AC3gH5Ed7u/zlcT72OIanQ6/8NIFN6Hm0/nJfRUf/3ngNSqvvSXxX6zLEurU7684XTICw3wGlmGyA== +"@juicedollar/jusd@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@juicedollar/jusd/-/jusd-1.0.2.tgz#a6b02599c8c990f30c24096ba989f5cfb90cff4d" + integrity sha512-QMVoedo6z1Ow6nDu6M5IFFKg9yHEkTAVyY4Y6d54os59cChJlDDrhKjolo5XGO2gb1F7J2rhW6cFV+ARceU1dQ== dependencies: "@openzeppelin/contracts" "^5.1.0" hardhat-abi-exporter "^2.10.0" From 0ba67fe42ffb338e78d72416285f37e123bf9bb2 Mon Sep 17 00:00:00 2001 From: TaprootFreak <142087526+TaprootFreak@users.noreply.github.com> Date: Wed, 26 Nov 2025 22:23:29 +0100 Subject: [PATCH 2/8] Merge pull request #3 from JuiceDollar/feature/default-position-endpoint Add GET /positions/default endpoint for native coin minting --- positions/positions.controller.ts | 9 +++++++++ positions/positions.service.ts | 21 +++++++++++++++++++++ positions/positions.types.ts | 13 +++++++++++++ 3 files changed, 43 insertions(+) diff --git a/positions/positions.controller.ts b/positions/positions.controller.ts index d759097..04eae3c 100644 --- a/positions/positions.controller.ts +++ b/positions/positions.controller.ts @@ -3,6 +3,7 @@ import { PositionsService } from './positions.service'; import { ApiMintingUpdateListing, ApiMintingUpdateMapping, + ApiPositionDefault, ApiPositionsListing, ApiPositionsMapping, ApiPositionsOwners, @@ -14,6 +15,14 @@ import { ApiResponse, ApiTags } from '@nestjs/swagger'; export class PositionsController { constructor(private readonly positionsService: PositionsService) {} + @Get('default') + @ApiResponse({ + description: 'Returns the default position for native coin minting', + }) + getDefault(): ApiPositionDefault { + return this.positionsService.getDefaultPosition(); + } + @Get('list') @ApiResponse({ description: 'Returns a list of all positions', diff --git a/positions/positions.service.ts b/positions/positions.service.ts index 4a14192..cf6bef2 100644 --- a/positions/positions.service.ts +++ b/positions/positions.service.ts @@ -8,6 +8,7 @@ import { CONFIG, VIEM_CONFIG } from '../api.config'; import { ApiMintingUpdateListing, ApiMintingUpdateMapping, + ApiPositionDefault, ApiPositionsListing, ApiPositionsMapping, ApiPositionsOwners, @@ -18,6 +19,22 @@ import { PositionsQueryObjectArray, } from './positions.types'; +// Hardcoded default position for native coin minting (WcBTC) +// Values fetched from blockchain at 0x03a7A7c133008658B746e6ef7836D493BE9B72f7 +// TODO: Make this dynamic in a future update +const DEFAULT_POSITION: ApiPositionDefault = { + position: '0x03a7A7c133008658B746e6ef7836D493BE9B72f7' as Address, + collateral: '0x8d0c9d1c17aE5e40ffF9bE350f57840E9E66Cd93' as Address, // WCBTC on Citrea Testnet + collateralSymbol: 'WCBTC', + collateralDecimals: 18, + price: '500000000000000000000000000', + minimumCollateral: '10000000000000', // 0.00001 WCBTC + availableForClones: '994975446998993918277164200', + expiration: 1794782602, // 2026-11-15 + reserveContribution: 200000, // 20% + annualInterestPPM: 30000, // 3% (riskPremiumPPM, leadrate will be added dynamically) +}; + @Injectable() export class PositionsService { private readonly logger = new Logger(this.constructor.name); @@ -27,6 +44,10 @@ export class PositionsService { constructor() {} + getDefaultPosition(): ApiPositionDefault { + return DEFAULT_POSITION; + } + getPositionsList(): ApiPositionsListing { const pos = Object.values(this.fetchedPositions) as PositionQuery[]; return { diff --git a/positions/positions.types.ts b/positions/positions.types.ts index b2af0fa..f9e680a 100644 --- a/positions/positions.types.ts +++ b/positions/positions.types.ts @@ -117,3 +117,16 @@ export type ApiMintingUpdateMapping = { positions: Address[]; map: MintingUpdateQueryObjectArray; }; + +export type ApiPositionDefault = { + position: Address; + collateral: Address; + collateralSymbol: string; + collateralDecimals: number; + price: string; + minimumCollateral: string; + availableForClones: string; + expiration: number; + reserveContribution: number; + annualInterestPPM: number; +}; From 1a7a7aa8215597ee874557f935ed60536e567ea0 Mon Sep 17 00:00:00 2001 From: TaprootFreak <142087526+TaprootFreak@users.noreply.github.com> Date: Thu, 27 Nov 2025 13:41:38 +0100 Subject: [PATCH 3/8] Update default position to 0x0B2C4886639aEF7BE38CA5c1f943c7aff9Bc884b (#4) --- positions/positions.service.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/positions/positions.service.ts b/positions/positions.service.ts index cf6bef2..fae68bb 100644 --- a/positions/positions.service.ts +++ b/positions/positions.service.ts @@ -19,20 +19,20 @@ import { PositionsQueryObjectArray, } from './positions.types'; -// Hardcoded default position for native coin minting (WcBTC) -// Values fetched from blockchain at 0x03a7A7c133008658B746e6ef7836D493BE9B72f7 +// Hardcoded default position for native coin minting (WCBTC) +// Values fetched from blockchain at 0x0B2C4886639aEF7BE38CA5c1f943c7aff9Bc884b // TODO: Make this dynamic in a future update const DEFAULT_POSITION: ApiPositionDefault = { - position: '0x03a7A7c133008658B746e6ef7836D493BE9B72f7' as Address, + position: '0x0B2C4886639aEF7BE38CA5c1f943c7aff9Bc884b' as Address, collateral: '0x8d0c9d1c17aE5e40ffF9bE350f57840E9E66Cd93' as Address, // WCBTC on Citrea Testnet collateralSymbol: 'WCBTC', collateralDecimals: 18, - price: '500000000000000000000000000', - minimumCollateral: '10000000000000', // 0.00001 WCBTC - availableForClones: '994975446998993918277164200', - expiration: 1794782602, // 2026-11-15 + price: '50000000000000000000000', // 50'000 JUSD per WCBTC + minimumCollateral: '2000000000000000', // 0.002 WCBTC + availableForClones: '99999800000000000000001000', + expiration: 1795743987, // 2026-11-26 reserveContribution: 200000, // 20% - annualInterestPPM: 30000, // 3% (riskPremiumPPM, leadrate will be added dynamically) + annualInterestPPM: 110000, // 11% (riskPremiumPPM, leadrate will be added dynamically) }; @Injectable() From d250c812495f4a399851500cd9989b0e3d299da3 Mon Sep 17 00:00:00 2001 From: TaprootFreak <142087526+TaprootFreak@users.noreply.github.com> Date: Thu, 27 Nov 2025 14:47:38 +0100 Subject: [PATCH 4/8] Fetch availableForClones dynamically from cached positions (#5) * Fetch availableForClones dynamically from cached positions * Prevent crash on start --------- Co-authored-by: Daniel Padrino --- positions/positions.service.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/positions/positions.service.ts b/positions/positions.service.ts index fae68bb..f8cdc01 100644 --- a/positions/positions.service.ts +++ b/positions/positions.service.ts @@ -45,7 +45,11 @@ export class PositionsService { constructor() {} getDefaultPosition(): ApiPositionDefault { - return DEFAULT_POSITION; + const cached = this.fetchedPositions[DEFAULT_POSITION.position.toLowerCase() as Address]; + return { + ...DEFAULT_POSITION, + availableForClones: cached?.availableForClones ?? DEFAULT_POSITION.availableForClones, + }; } getPositionsList(): ApiPositionsListing { From 81688985af6022bf028640f706eecd6cdd1933b1 Mon Sep 17 00:00:00 2001 From: TaprootFreak <142087526+TaprootFreak@users.noreply.github.com> Date: Wed, 3 Dec 2025 16:15:33 +0100 Subject: [PATCH 5/8] chore: update @juicedollar/jusd to v1.0.4 (#6) * chore: update @juicedollar/jusd to v1.0.4 Update dependency to include native cBTC support for challenge and liquidation flows. * adjust default position values --------- Co-authored-by: lapatric <42653152+lapatric@users.noreply.github.com> --- package.json | 2 +- positions/positions.service.ts | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index b12c714..6c3a7ef 100644 --- a/package.json +++ b/package.json @@ -32,7 +32,7 @@ }, "dependencies": { "@apollo/client": "^3.10.5", - "@juicedollar/jusd": "^1.0.2", + "@juicedollar/jusd": "^1.0.4", "@nestjs/common": "^10.0.0", "@nestjs/config": "^3.2.3", "@nestjs/core": "^10.0.0", diff --git a/positions/positions.service.ts b/positions/positions.service.ts index f8cdc01..2ddd98e 100644 --- a/positions/positions.service.ts +++ b/positions/positions.service.ts @@ -20,19 +20,19 @@ import { } from './positions.types'; // Hardcoded default position for native coin minting (WCBTC) -// Values fetched from blockchain at 0x0B2C4886639aEF7BE38CA5c1f943c7aff9Bc884b +// Values fetched from blockchain at 0xc7Cfb0708aC6ADC81f64ED2793b212bb6AE438aE // TODO: Make this dynamic in a future update const DEFAULT_POSITION: ApiPositionDefault = { - position: '0x0B2C4886639aEF7BE38CA5c1f943c7aff9Bc884b' as Address, + position: '0xc7Cfb0708aC6ADc81f64ED2793b212bb6AE438aE' as Address, collateral: '0x8d0c9d1c17aE5e40ffF9bE350f57840E9E66Cd93' as Address, // WCBTC on Citrea Testnet collateralSymbol: 'WCBTC', collateralDecimals: 18, price: '50000000000000000000000', // 50'000 JUSD per WCBTC minimumCollateral: '2000000000000000', // 0.002 WCBTC - availableForClones: '99999800000000000000001000', - expiration: 1795743987, // 2026-11-26 + availableForClones: '100000000000000000000000000', + expiration: 1796307151, // 2026-12-03 reserveContribution: 200000, // 20% - annualInterestPPM: 110000, // 11% (riskPremiumPPM, leadrate will be added dynamically) + annualInterestPPM: 100000, // 10% (riskPremiumPPM, leadrate will be added dynamically) }; @Injectable() From 181eb0cef77cb2e5b2e38c6543735f0ec2466413 Mon Sep 17 00:00:00 2001 From: TaprootFreak <142087526+TaprootFreak@users.noreply.github.com> Date: Wed, 3 Dec 2025 16:43:22 +0100 Subject: [PATCH 6/8] chore: update yarn.lock for @juicedollar/jusd v1.0.4 --- yarn.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/yarn.lock b/yarn.lock index 51419b4..4b4a86c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -902,10 +902,10 @@ "@jridgewell/resolve-uri" "^3.1.0" "@jridgewell/sourcemap-codec" "^1.4.14" -"@juicedollar/jusd@^1.0.2": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@juicedollar/jusd/-/jusd-1.0.2.tgz#a6b02599c8c990f30c24096ba989f5cfb90cff4d" - integrity sha512-QMVoedo6z1Ow6nDu6M5IFFKg9yHEkTAVyY4Y6d54os59cChJlDDrhKjolo5XGO2gb1F7J2rhW6cFV+ARceU1dQ== +"@juicedollar/jusd@^1.0.4": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@juicedollar/jusd/-/jusd-1.0.4.tgz#898fd0bd56aceb7d8243973a146940e280da75c8" + integrity sha512-MbWPptrX1HiDim8aRBHkH51UhaeyUVQ/aPDeEoaQHnJwWJ25ApPxNjGbNA17cg94Fh1gptPeYXemCWD0SqwR5Q== dependencies: "@openzeppelin/contracts" "^5.1.0" hardhat-abi-exporter "^2.10.0" From 152bbf5de427e36550621fc1f4726d069f30945b Mon Sep 17 00:00:00 2001 From: TaprootFreak <142087526+TaprootFreak@users.noreply.github.com> Date: Mon, 15 Dec 2025 15:12:49 +0100 Subject: [PATCH 7/8] Update default position to 0xE2D4Ca089457ECfabF89F472568eac4e94b21d8C (#7) --- positions/positions.service.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/positions/positions.service.ts b/positions/positions.service.ts index 2ddd98e..54aaa8b 100644 --- a/positions/positions.service.ts +++ b/positions/positions.service.ts @@ -20,19 +20,19 @@ import { } from './positions.types'; // Hardcoded default position for native coin minting (WCBTC) -// Values fetched from blockchain at 0xc7Cfb0708aC6ADC81f64ED2793b212bb6AE438aE +// Values fetched from blockchain at 0xE2D4Ca089457ECfabF89F472568eac4e94b21d8C // TODO: Make this dynamic in a future update const DEFAULT_POSITION: ApiPositionDefault = { - position: '0xc7Cfb0708aC6ADc81f64ED2793b212bb6AE438aE' as Address, + position: '0xE2D4Ca089457ECfabF89F472568eac4e94b21d8C' as Address, collateral: '0x8d0c9d1c17aE5e40ffF9bE350f57840E9E66Cd93' as Address, // WCBTC on Citrea Testnet collateralSymbol: 'WCBTC', collateralDecimals: 18, price: '50000000000000000000000', // 50'000 JUSD per WCBTC minimumCollateral: '2000000000000000', // 0.002 WCBTC availableForClones: '100000000000000000000000000', - expiration: 1796307151, // 2026-12-03 + expiration: 1797334468, // 2026-12-15 reserveContribution: 200000, // 20% - annualInterestPPM: 100000, // 10% (riskPremiumPPM, leadrate will be added dynamically) + annualInterestPPM: 100000, // 10% }; @Injectable() From 338dfb108f6334ef840c172b976de6d4c501ffba Mon Sep 17 00:00:00 2001 From: TaprootFreak <142087526+TaprootFreak@users.noreply.github.com> Date: Mon, 15 Dec 2025 16:00:19 +0100 Subject: [PATCH 8/8] feat: load default position dynamically from Ponder (#9) - Update @juicedollar/jusd to v1.0.6 - Use genesisPosition address from NPM package - Fetch all position data from Ponder cache instead of hardcoded values --- package.json | 2 +- positions/positions.controller.ts | 2 +- positions/positions.service.ts | 34 ++++++++++++++----------------- yarn.lock | 8 ++++---- 4 files changed, 21 insertions(+), 25 deletions(-) diff --git a/package.json b/package.json index 6c3a7ef..daa6567 100644 --- a/package.json +++ b/package.json @@ -32,7 +32,7 @@ }, "dependencies": { "@apollo/client": "^3.10.5", - "@juicedollar/jusd": "^1.0.4", + "@juicedollar/jusd": "1.0.6", "@nestjs/common": "^10.0.0", "@nestjs/config": "^3.2.3", "@nestjs/core": "^10.0.0", diff --git a/positions/positions.controller.ts b/positions/positions.controller.ts index 04eae3c..fb7feac 100644 --- a/positions/positions.controller.ts +++ b/positions/positions.controller.ts @@ -19,7 +19,7 @@ export class PositionsController { @ApiResponse({ description: 'Returns the default position for native coin minting', }) - getDefault(): ApiPositionDefault { + getDefault(): ApiPositionDefault | null { return this.positionsService.getDefaultPosition(); } diff --git a/positions/positions.service.ts b/positions/positions.service.ts index 54aaa8b..7ef7093 100644 --- a/positions/positions.service.ts +++ b/positions/positions.service.ts @@ -19,21 +19,8 @@ import { PositionsQueryObjectArray, } from './positions.types'; -// Hardcoded default position for native coin minting (WCBTC) -// Values fetched from blockchain at 0xE2D4Ca089457ECfabF89F472568eac4e94b21d8C -// TODO: Make this dynamic in a future update -const DEFAULT_POSITION: ApiPositionDefault = { - position: '0xE2D4Ca089457ECfabF89F472568eac4e94b21d8C' as Address, - collateral: '0x8d0c9d1c17aE5e40ffF9bE350f57840E9E66Cd93' as Address, // WCBTC on Citrea Testnet - collateralSymbol: 'WCBTC', - collateralDecimals: 18, - price: '50000000000000000000000', // 50'000 JUSD per WCBTC - minimumCollateral: '2000000000000000', // 0.002 WCBTC - availableForClones: '100000000000000000000000000', - expiration: 1797334468, // 2026-12-15 - reserveContribution: 200000, // 20% - annualInterestPPM: 100000, // 10% -}; +// Genesis position address from NPM package +const GENESIS_POSITION = ADDRESS[CONFIG.chain.id].genesisPosition as Address; @Injectable() export class PositionsService { @@ -44,11 +31,20 @@ export class PositionsService { constructor() {} - getDefaultPosition(): ApiPositionDefault { - const cached = this.fetchedPositions[DEFAULT_POSITION.position.toLowerCase() as Address]; + getDefaultPosition(): ApiPositionDefault | null { + const cached = this.fetchedPositions[GENESIS_POSITION.toLowerCase() as Address]; + if (!cached) return null; return { - ...DEFAULT_POSITION, - availableForClones: cached?.availableForClones ?? DEFAULT_POSITION.availableForClones, + position: cached.position, + collateral: cached.collateral, + collateralSymbol: cached.collateralSymbol, + collateralDecimals: cached.collateralDecimals, + price: cached.price, + minimumCollateral: cached.minimumCollateral, + availableForClones: cached.availableForClones, + expiration: cached.expiration, + reserveContribution: cached.reserveContribution, + annualInterestPPM: cached.annualInterestPPM, }; } diff --git a/yarn.lock b/yarn.lock index 4b4a86c..bbd417a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -902,10 +902,10 @@ "@jridgewell/resolve-uri" "^3.1.0" "@jridgewell/sourcemap-codec" "^1.4.14" -"@juicedollar/jusd@^1.0.4": - version "1.0.4" - resolved "https://registry.yarnpkg.com/@juicedollar/jusd/-/jusd-1.0.4.tgz#898fd0bd56aceb7d8243973a146940e280da75c8" - integrity sha512-MbWPptrX1HiDim8aRBHkH51UhaeyUVQ/aPDeEoaQHnJwWJ25ApPxNjGbNA17cg94Fh1gptPeYXemCWD0SqwR5Q== +"@juicedollar/jusd@1.0.6": + version "1.0.6" + resolved "https://registry.yarnpkg.com/@juicedollar/jusd/-/jusd-1.0.6.tgz#5e28a415a71b1abd77d1c278ae2816b95fc72bb3" + integrity sha512-5fp4n5rAyq/pw6rEbCWEdJ0U5v50NHh/cR63gG+Km8aNj8GO1wxG53/cNuXku/45TWGGFsboDci18C4X8tdEOg== dependencies: "@openzeppelin/contracts" "^5.1.0" hardhat-abi-exporter "^2.10.0"