Concepts, value, and typical clone scenarios — less code.
Concepts, value, and typical clone scenarios — less code.
Підготовка контенту платформи Ring
Підготовка контенту платформи Ring
Підготовка контенту платформи Ring
Dual-rail: Token minting (this document) pairs with ERP settlements referral commission on the same orderReference. Overview: Affiliate enablement.
| Module | Path | Responsibility |
|---|---|---|
| Cookie capture | proxy.ts | First-touch ring_ref from ?ref= |
| Code registry | refcode-service.ts | CRUD codes per (userId, wallet) |
| Attribution | attribution-service.ts | Self-ref, first-purchase, wallet overlap guards |
| Reward ledger | referral-reward-service.ts | Fiat/credit paths, approval, oracle sizing |
| On-chain mint | reward-minter.ts | viem simulateContract + writeContract |
| Server wallet | lib/web3/server-wallet.ts | REFERRAL_MINTER_PRIVATE_KEY → viem account |
app/api/store/orders/route.ts resolves attribution before StoreOrdersService.createOrder. Referral fields are stored in the orders JSONB document:
referralCodereferrerUserIdreferrerWalletlib/payments/conductor/handlers/store-order.ts calls ReferralRewardService.onOrderPaid inside the Approved + isNew branch — after stock deduction and vendor settlement. Failures are logged but do not fail the webhook.
app/api/store/payments/credit/route.ts marks the order paid, deducts stock, writes settlements via settlement-pipeline.ts, then calls onOrderPaid with rail: 'crypto' (auto-approved mint).
handlers/membership-upgrade.ts → ReferralRewardService.onMembershipPaid when users.data.referredBy is set (first-touch signup attribution).
| Endpoint / component | Role |
|---|---|
POST /api/refcodes/track | trackRefcodeVisit — bumps visits + visitDaily[UTC date] (28-day prune) |
ReferralAttributionEffect | Public layout client beacon when ring_ref_visible is set |
ReferralCheckoutBadge | Review step reads ring_ref_visible |
checkout-referral-flash.ts | WayForPay redirect toast survival (30 min TTL) |
GET /api/cron/refcodes-mint | processApprovedRewards(20) — Authorization: Bearer $CRON_SECRET |
After on-chain success, reward-minter.ts loads copy via lib/i18n/refcodes-labels.ts:
getUserPreferredLocaleForNotifications(referrerUserId) — users.settings.language (DB-only, smoke-safe).getReferralMintNotificationCopy(locale, { amount, token }) — modules/refcodes.json → notifications.minted.createNotification with type REFERRAL_REWARD_MINTED.| Layer | Key |
|---|---|
| PostgreSQL | Unique index on referral_rewards (data->>'orderReference') |
| Service | rewardExistsForOrder short-circuit |
| Contract | paidOrders[orderRef] mapping — reverts ReferralRewards__AlreadyPaid |
orderRef on-chain = keccak256(bytes(orderReference)) where orderReference comes from PaymentConductor.
| Surface | Bundle keys |
|---|---|
| User/admin UI | locales/{en,uk,ru}/modules/refcodes.json — visits, stats, admin queue |
| Checkout toast | modules/store.json → checkout.referralApplied* |
| Mint notification | modules/refcodes.json → notifications.minted (server via refcodes-labels.ts) |
modRefcodes in lib/i18n/message-scopes.ts (authenticated + admin)REFCODES, ADMIN_REFCODES in constants/routes.ts| Environment | Database | Notes |
|---|---|---|
| ring-platform.org dev | ring_platform | Homebrew Postgres (bootstrap-brew-dev.sh) or Docker ring-postgres-dev |
| ring-platform.org prod | ring_platform | postgres.ring-platform-org.svc.cluster.local |
| ring-connect-software | ring_connect_software_dev / prod name | Separate clone DB |
| ring-ringdom-org | ring_ringdom_org | Separate clone DB |
Migration file: data/migrations/005_refcodes_schema.sql.
Dual-rail: Token minting (this document) pairs with ERP settlements referral commission on the same orderReference. Overview: Affiliate enablement.
| Module | Path | Responsibility |
|---|---|---|
| Cookie capture | proxy.ts | First-touch ring_ref from ?ref= |
| Code registry | refcode-service.ts | CRUD codes per (userId, wallet) |
| Attribution | attribution-service.ts | Self-ref, first-purchase, wallet overlap guards |
| Reward ledger | referral-reward-service.ts | Fiat/credit paths, approval, oracle sizing |
| On-chain mint | reward-minter.ts | viem simulateContract + writeContract |
| Server wallet | lib/web3/server-wallet.ts | REFERRAL_MINTER_PRIVATE_KEY → viem account |
app/api/store/orders/route.ts resolves attribution before StoreOrdersService.createOrder. Referral fields are stored in the orders JSONB document:
referralCodereferrerUserIdreferrerWalletlib/payments/conductor/handlers/store-order.ts calls ReferralRewardService.onOrderPaid inside the Approved + isNew branch — after stock deduction and vendor settlement. Failures are logged but do not fail the webhook.
app/api/store/payments/credit/route.ts marks the order paid, deducts stock, writes settlements via settlement-pipeline.ts, then calls onOrderPaid with rail: 'crypto' (auto-approved mint).
handlers/membership-upgrade.ts → ReferralRewardService.onMembershipPaid when users.data.referredBy is set (first-touch signup attribution).
| Endpoint / component | Role |
|---|---|
POST /api/refcodes/track | trackRefcodeVisit — bumps visits + visitDaily[UTC date] (28-day prune) |
ReferralAttributionEffect | Public layout client beacon when ring_ref_visible is set |
ReferralCheckoutBadge | Review step reads ring_ref_visible |
checkout-referral-flash.ts | WayForPay redirect toast survival (30 min TTL) |
GET /api/cron/refcodes-mint | processApprovedRewards(20) — Authorization: Bearer $CRON_SECRET |
After on-chain success, reward-minter.ts loads copy via lib/i18n/refcodes-labels.ts:
getUserPreferredLocaleForNotifications(referrerUserId) — users.settings.language (DB-only, smoke-safe).getReferralMintNotificationCopy(locale, { amount, token }) — modules/refcodes.json → notifications.minted.createNotification with type REFERRAL_REWARD_MINTED.| Layer | Key |
|---|---|
| PostgreSQL | Unique index on referral_rewards (data->>'orderReference') |
| Service | rewardExistsForOrder short-circuit |
| Contract | paidOrders[orderRef] mapping — reverts ReferralRewards__AlreadyPaid |
orderRef on-chain = keccak256(bytes(orderReference)) where orderReference comes from PaymentConductor.
| Surface | Bundle keys |
|---|---|
| User/admin UI | locales/{en,uk,ru}/modules/refcodes.json — visits, stats, admin queue |
| Checkout toast | modules/store.json → checkout.referralApplied* |
| Mint notification | modules/refcodes.json → notifications.minted (server via refcodes-labels.ts) |
modRefcodes in lib/i18n/message-scopes.ts (authenticated + admin)REFCODES, ADMIN_REFCODES in constants/routes.ts| Environment | Database | Notes |
|---|---|---|
| ring-platform.org dev | ring_platform | Homebrew Postgres (bootstrap-brew-dev.sh) or Docker ring-postgres-dev |
| ring-platform.org prod | ring_platform | postgres.ring-platform-org.svc.cluster.local |
| ring-connect-software | ring_connect_software_dev / prod name | Separate clone DB |
| ring-ringdom-org | ring_ringdom_org | Separate clone DB |
Migration file: data/migrations/005_refcodes_schema.sql.
Dual-rail: Token minting (this document) pairs with ERP settlements referral commission on the same orderReference. Overview: Affiliate enablement.
| Module | Path | Responsibility |
|---|---|---|
| Cookie capture | proxy.ts | First-touch ring_ref from ?ref= |
| Code registry | refcode-service.ts | CRUD codes per (userId, wallet) |
| Attribution | attribution-service.ts | Self-ref, first-purchase, wallet overlap guards |
| Reward ledger | referral-reward-service.ts | Fiat/credit paths, approval, oracle sizing |
| On-chain mint | reward-minter.ts | viem simulateContract + writeContract |
| Server wallet | lib/web3/server-wallet.ts | REFERRAL_MINTER_PRIVATE_KEY → viem account |
app/api/store/orders/route.ts resolves attribution before StoreOrdersService.createOrder. Referral fields are stored in the orders JSONB document:
referralCodereferrerUserIdreferrerWalletlib/payments/conductor/handlers/store-order.ts calls ReferralRewardService.onOrderPaid inside the Approved + isNew branch — after stock deduction and vendor settlement. Failures are logged but do not fail the webhook.
app/api/store/payments/credit/route.ts marks the order paid, deducts stock, writes settlements via settlement-pipeline.ts, then calls onOrderPaid with rail: 'crypto' (auto-approved mint).
handlers/membership-upgrade.ts → ReferralRewardService.onMembershipPaid when users.data.referredBy is set (first-touch signup attribution).
| Endpoint / component | Role |
|---|---|
POST /api/refcodes/track | trackRefcodeVisit — bumps visits + visitDaily[UTC date] (28-day prune) |
ReferralAttributionEffect | Public layout client beacon when ring_ref_visible is set |
ReferralCheckoutBadge | Review step reads ring_ref_visible |
checkout-referral-flash.ts | WayForPay redirect toast survival (30 min TTL) |
GET /api/cron/refcodes-mint | processApprovedRewards(20) — Authorization: Bearer $CRON_SECRET |
After on-chain success, reward-minter.ts loads copy via lib/i18n/refcodes-labels.ts:
getUserPreferredLocaleForNotifications(referrerUserId) — users.settings.language (DB-only, smoke-safe).getReferralMintNotificationCopy(locale, { amount, token }) — modules/refcodes.json → notifications.minted.createNotification with type REFERRAL_REWARD_MINTED.| Layer | Key |
|---|---|
| PostgreSQL | Unique index on referral_rewards (data->>'orderReference') |
| Service | rewardExistsForOrder short-circuit |
| Contract | paidOrders[orderRef] mapping — reverts ReferralRewards__AlreadyPaid |
orderRef on-chain = keccak256(bytes(orderReference)) where orderReference comes from PaymentConductor.
| Surface | Bundle keys |
|---|---|
| User/admin UI | locales/{en,uk,ru}/modules/refcodes.json — visits, stats, admin queue |
| Checkout toast | modules/store.json → checkout.referralApplied* |
| Mint notification | modules/refcodes.json → notifications.minted (server via refcodes-labels.ts) |
modRefcodes in lib/i18n/message-scopes.ts (authenticated + admin)REFCODES, ADMIN_REFCODES in constants/routes.ts| Environment | Database | Notes |
|---|---|---|
| ring-platform.org dev | ring_platform | Homebrew Postgres (bootstrap-brew-dev.sh) or Docker ring-postgres-dev |
| ring-platform.org prod | ring_platform | postgres.ring-platform-org.svc.cluster.local |
| ring-connect-software | ring_connect_software_dev / prod name | Separate clone DB |
| ring-ringdom-org | ring_ringdom_org | Separate clone DB |
Migration file: data/migrations/005_refcodes_schema.sql.
initialize(admin, operator, token, mode)
├─ DEFAULT_ADMIN_ROLE → admin (upgrade, pause, setRewardToken/Mode)
└─ OPERATOR_ROLE → operator (payReferral)
MINT mode: token must authorize proxy to mint
TRANSFER mode: contract must hold token balance (treasury-funded)
initialize(admin, operator, token, mode)
├─ DEFAULT_ADMIN_ROLE → admin (upgrade, pause, setRewardToken/Mode)
└─ OPERATOR_ROLE → operator (payReferral)
MINT mode: token must authorize proxy to mint
TRANSFER mode: contract must hold token balance (treasury-funded)
initialize(admin, operator, token, mode)
├─ DEFAULT_ADMIN_ROLE → admin (upgrade, pause, setRewardToken/Mode)
└─ OPERATOR_ROLE → operator (payReferral)
MINT mode: token must authorize proxy to mint
TRANSFER mode: contract must hold token balance (treasury-funded)