Add steps to publish PricingRecord
and use it for determining cost of deployments (#4)
Part of https://www.notion.so/Laconic-Mainnet-Plan-1eca6b22d47280569cd0d1e6d711d949 Co-authored-by: Shreerang Kale <shreerangkale@gmail.com> Reviewed-on: #4 Co-authored-by: shreerang <shreerang@noreply.git.vdb.to> Co-committed-by: shreerang <shreerang@noreply.git.vdb.to>
This commit is contained in:
parent
fbe4eed31d
commit
452c4db5f8
15
.env.example
15
.env.example
@ -1,11 +1,10 @@
|
|||||||
# Client-side environment variables (must be prefixed with NEXT_PUBLIC_)
|
# Client-side environment variables must be prefixed with NEXT_PUBLIC_
|
||||||
|
|
||||||
# Solana Payment Configuration
|
# Solana Payment Configuration
|
||||||
# TODO: Use different RPC URL or use browser wallet
|
# TODO: Use different RPC URL
|
||||||
NEXT_PUBLIC_SOLANA_RPC_URL=https://skilled-prettiest-seed.solana-mainnet.quiknode.pro/eeecfebd04e345f69f1900cc3483cbbfea02a158
|
NEXT_PUBLIC_SOLANA_RPC_URL=https://skilled-prettiest-seed.solana-mainnet.quiknode.pro/eeecfebd04e345f69f1900cc3483cbbfea02a158
|
||||||
NEXT_PUBLIC_SOLANA_TOKEN_MINT_ADDRESS=71Jvq4Epe2FCJ7JFSF7jLXdNk1Wy4Bhqd9iL6bEFELvg
|
NEXT_PUBLIC_SOLANA_TOKEN_MINT_ADDRESS=71Jvq4Epe2FCJ7JFSF7jLXdNk1Wy4Bhqd9iL6bEFELvg
|
||||||
NEXT_PUBLIC_SOLANA_TOKEN_SYMBOL=GOR
|
NEXT_PUBLIC_SOLANA_TOKEN_SYMBOL=GOR
|
||||||
NEXT_PUBLIC_SOLANA_PAYMENT_AMOUNT_USD=5
|
|
||||||
|
|
||||||
# Gorbagana Chain Configuration
|
# Gorbagana Chain Configuration
|
||||||
NEXT_PUBLIC_GORBAGANA_RPC_URL=https://rpc.gorbagana.wtf
|
NEXT_PUBLIC_GORBAGANA_RPC_URL=https://rpc.gorbagana.wtf
|
||||||
@ -17,12 +16,12 @@ NEXT_PUBLIC_SOLANA_TOKEN_RECIPIENT_ADDRESS=FFDx3SdAEeXrp6BTmStB4BDHpctGsaasZq4FF
|
|||||||
# UI Configuration
|
# UI Configuration
|
||||||
NEXT_PUBLIC_EXAMPLE_URL=https://git.vdb.to/cerc-io/test-progressive-web-app
|
NEXT_PUBLIC_EXAMPLE_URL=https://git.vdb.to/cerc-io/test-progressive-web-app
|
||||||
|
|
||||||
# Server-side environment variables
|
|
||||||
|
|
||||||
# Laconic Registry Configuration
|
# Laconic Registry Configuration
|
||||||
REGISTRY_CHAIN_ID=laconic-mainnet
|
NEXT_PUBLIC_REGISTRY_CHAIN_ID=laconic-mainnet
|
||||||
REGISTRY_RPC_ENDPOINT=https://laconicd-mainnet-1.laconic.com
|
NEXT_PUBLIC_REGISTRY_RPC_ENDPOINT=https://laconicd-mainnet-1.laconic.com
|
||||||
REGISTRY_GQL_ENDPOINT=https://laconicd-mainnet-1.laconic.com/graphql
|
NEXT_PUBLIC_REGISTRY_GQL_ENDPOINT=https://laconicd-mainnet-1.laconic.com/graphql
|
||||||
|
NEXT_PUBLIC_ALNT_COST_LRN=lrn://laconic/pricing/alnt
|
||||||
|
NEXT_PUBLIC_DEPLOYMENT_COST_LRN=lrn://laconic/pricing/webapp-deployment
|
||||||
REGISTRY_GAS_PRICE=0.001
|
REGISTRY_GAS_PRICE=0.001
|
||||||
REGISTRY_BOND_ID=
|
REGISTRY_BOND_ID=
|
||||||
REGISTRY_AUTHORITY=
|
REGISTRY_AUTHORITY=
|
||||||
|
3
.gitignore
vendored
3
.gitignore
vendored
@ -43,3 +43,6 @@ yarn-error.log*
|
|||||||
|
|
||||||
# typescript
|
# typescript
|
||||||
*.tsbuildinfo
|
*.tsbuildinfo
|
||||||
|
|
||||||
|
# Reveal file out dir
|
||||||
|
out
|
@ -106,9 +106,9 @@ NEXT_PUBLIC_EXAMPLE_URL=https://git.vdb.to/cerc-io/test-progressive-web-app
|
|||||||
|
|
||||||
### Server-side Variables
|
### Server-side Variables
|
||||||
```bash
|
```bash
|
||||||
REGISTRY_CHAIN_ID=laconic-mainnet
|
NEXT_PUBLIC_REGISTRY_CHAIN_ID=laconic-mainnet
|
||||||
REGISTRY_GQL_ENDPOINT=https://laconicd-mainnet-1.laconic.com/api
|
NEXT_PUBLIC_REGISTRY_GQL_ENDPOINT=https://laconicd-mainnet-1.laconic.com/api
|
||||||
REGISTRY_RPC_ENDPOINT=https://laconicd-mainnet-1.laconic.com
|
NEXT_PUBLIC_REGISTRY_RPC_ENDPOINT=https://laconicd-mainnet-1.laconic.com
|
||||||
REGISTRY_BOND_ID=<BOND_ID>
|
REGISTRY_BOND_ID=<BOND_ID>
|
||||||
REGISTRY_AUTHORITY=<AUTHORITY_NAME>
|
REGISTRY_AUTHORITY=<AUTHORITY_NAME>
|
||||||
REGISTRY_USER_KEY=<PRIVATE_KEY>
|
REGISTRY_USER_KEY=<PRIVATE_KEY>
|
||||||
|
102
README.md
102
README.md
@ -20,35 +20,9 @@ A simple Next.js frontend that allows users to pay in GOR tokens (configurable S
|
|||||||
- Solana wallet browser extension (Phantom or Solflare)
|
- Solana wallet browser extension (Phantom or Solflare)
|
||||||
- Access to a Laconic Registry node
|
- Access to a Laconic Registry node
|
||||||
|
|
||||||
## Environment Variables
|
## Deploy to production
|
||||||
|
|
||||||
Copy the `.env.local.example` file to `.env.local` and fill in the required variables:
|
Follow [these steps](./deploy/README.md) to deploy this app to production
|
||||||
|
|
||||||
```bash
|
|
||||||
cp .env.local.example .env.local
|
|
||||||
```
|
|
||||||
|
|
||||||
Required environment variables:
|
|
||||||
|
|
||||||
Client-side (must be prefixed with NEXT_PUBLIC_):
|
|
||||||
- `NEXT_PUBLIC_SOLANA_RPC_URL` - The RPC URL for the Solana blockchain
|
|
||||||
- `NEXT_PUBLIC_SOLANA_TOKEN_MINT_ADDRESS` - The mint address of the SPL token to accept
|
|
||||||
- `NEXT_PUBLIC_SOLANA_TOKEN_RECIPIENT_ADDRESS` - The Solana address that will receive token payments
|
|
||||||
- `NEXT_PUBLIC_SOLANA_TOKEN_SYMBOL` - The token symbol to display (e.g., "GOR")
|
|
||||||
- `NEXT_PUBLIC_SOLANA_TOKEN_DECIMALS` - The number of decimals for the token (e.g., 6)
|
|
||||||
- `NEXT_PUBLIC_SOLANA_PAYMENT_AMOUNT` - The fixed payment amount required (e.g., 400)
|
|
||||||
- `NEXT_PUBLIC_DOMAIN_SUFFIX` - Optional suffix to append to DNS names in the UI (e.g. ".example.com")
|
|
||||||
- `NEXT_PUBLIC_EXAMPLE_URL` - Example URL to pre-fill in the URL form (e.g. "https://github.com/cerc-io/laconic-registry-cli")
|
|
||||||
|
|
||||||
Server-side:
|
|
||||||
- `REGISTRY_CHAIN_ID` - The chain ID for the Laconic Registry
|
|
||||||
- `REGISTRY_GQL_ENDPOINT` - The GraphQL endpoint for the Laconic Registry
|
|
||||||
- `REGISTRY_RPC_ENDPOINT` - The RPC endpoint for the Laconic Registry
|
|
||||||
- `REGISTRY_BOND_ID` - The bond ID to use for Laconic Registry records
|
|
||||||
- `REGISTRY_AUTHORITY` - The authority for Laconic Registry LRNs
|
|
||||||
- `REGISTRY_USER_KEY` - The private key for Laconic Registry transactions (also used for LNT transfers)
|
|
||||||
- `APP_NAME` - The name of the application (used in record creation, defaults to "gor-deploy")
|
|
||||||
- `DEPLOYER_LRN` - The LRN of the deployer
|
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
@ -58,6 +32,35 @@ npm install
|
|||||||
|
|
||||||
## Development
|
## Development
|
||||||
|
|
||||||
|
Copy the `.env.example` file to `.env.local` and fill in the required variables:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cp .env.example .env.local
|
||||||
|
```
|
||||||
|
|
||||||
|
Required environment variables:
|
||||||
|
|
||||||
|
Client-side (must be prefixed with NEXT_PUBLIC_):
|
||||||
|
- `NEXT_PUBLIC_SOLANA_RPC_URL` - The RPC URL for the Solana blockchain (SPL token transactions)
|
||||||
|
- `NEXT_PUBLIC_SOLANA_TOKEN_MINT_ADDRESS` - The mint address of the SPL token to accept
|
||||||
|
- `NEXT_PUBLIC_SOLANA_TOKEN_SYMBOL` - The token symbol to display (e.g., "GOR")
|
||||||
|
- `NEXT_PUBLIC_GORBAGANA_RPC_URL` - The RPC URL for the Gorbagana blockchain (native GOR transactions)
|
||||||
|
- `NEXT_PUBLIC_ENABLE_NATIVE_GOR_TRANSFER` - Enable native GOR token transfers (true/false)
|
||||||
|
- `NEXT_PUBLIC_SOLANA_TOKEN_RECIPIENT_ADDRESS` - The Solana address that will receive token payments
|
||||||
|
- `NEXT_PUBLIC_EXAMPLE_URL` - Example URL to pre-fill in the URL form
|
||||||
|
- `NEXT_PUBLIC_REGISTRY_CHAIN_ID` - The laconicd chain ID for the Laconic Registry
|
||||||
|
- `NEXT_PUBLIC_REGISTRY_RPC_ENDPOINT` - The laconicd RPC endpoint for the Laconic Registry
|
||||||
|
- `NEXT_PUBLIC_REGISTRY_GQL_ENDPOINT` - The laconicd GraphQL endpoint for the Laconic Registry
|
||||||
|
- `NEXT_PUBLIC_ALNT_COST_LRN` - LRN for ALNT token pricing
|
||||||
|
- `NEXT_PUBLIC_DEPLOYMENT_COST_LRN` - LRN for deployment cost pricing
|
||||||
|
- `NEXT_PUBLIC_DOMAIN_SUFFIX` - Optional suffix to append to DNS names in the UI (e.g. ".example.com")
|
||||||
|
|
||||||
|
Server-side:
|
||||||
|
- `REGISTRY_BOND_ID` - The bond ID to use for Laconic Registry records
|
||||||
|
- `REGISTRY_AUTHORITY` - The authority for Laconic Registry LRNs
|
||||||
|
- `REGISTRY_USER_KEY` - The private key for Laconic Registry transactions (also used for LNT transfers)
|
||||||
|
- `DEPLOYER_LRN` - The LRN of the deployer
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npm run dev
|
npm run dev
|
||||||
```
|
```
|
||||||
@ -130,43 +133,6 @@ This application was built with reference to:
|
|||||||
- `snowballtools-base/packages/backend/src/registry.ts`
|
- `snowballtools-base/packages/backend/src/registry.ts`
|
||||||
- Original `hosted-frontends/deploy-atom.sh` (adapted for Solana/GOR)
|
- Original `hosted-frontends/deploy-atom.sh` (adapted for Solana/GOR)
|
||||||
|
|
||||||
## Deployment to Production
|
|
||||||
|
|
||||||
To deploy this application to production, follow these steps:
|
|
||||||
|
|
||||||
1. Clone the repository
|
|
||||||
2. Install dependencies: `npm install`
|
|
||||||
3. Create a production build: `npm run build`
|
|
||||||
4. Set up all required environment variables in your production environment
|
|
||||||
5. Start the production server: `npm start`
|
|
||||||
|
|
||||||
For containerized deployments, you can use the following Dockerfile:
|
|
||||||
|
|
||||||
```dockerfile
|
|
||||||
FROM node:18-alpine
|
|
||||||
|
|
||||||
WORKDIR /app
|
|
||||||
|
|
||||||
COPY package*.json ./
|
|
||||||
RUN npm ci
|
|
||||||
|
|
||||||
COPY . .
|
|
||||||
RUN npm run build
|
|
||||||
|
|
||||||
EXPOSE 3000
|
|
||||||
|
|
||||||
ENV NODE_ENV=production
|
|
||||||
|
|
||||||
CMD ["npm", "start"]
|
|
||||||
```
|
|
||||||
|
|
||||||
Build and run the Docker container:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
docker build -t gor-deploy .
|
|
||||||
docker run -p 3000:3000 --env-file .env.production gor-deploy
|
|
||||||
```
|
|
||||||
|
|
||||||
## Known Issues
|
## Known Issues
|
||||||
|
|
||||||
- You may see a deprecated Buffer() warning during build. This comes from dependencies in the registry-sdk. This doesn't affect functionality.
|
- You may see a deprecated Buffer() warning during build. This comes from dependencies in the registry-sdk. This doesn't affect functionality.
|
||||||
@ -181,12 +147,6 @@ docker run -p 3000:3000 --env-file .env.production gor-deploy
|
|||||||
- **Connection issues**: Ensure the wallet is unlocked and try refreshing the page.
|
- **Connection issues**: Ensure the wallet is unlocked and try refreshing the page.
|
||||||
- **Transaction failures**: Check that you have sufficient SOL for transaction fees and enough tokens for the payment.
|
- **Transaction failures**: Check that you have sufficient SOL for transaction fees and enough tokens for the payment.
|
||||||
|
|
||||||
### Token Configuration
|
|
||||||
|
|
||||||
- **Wrong token**: Verify the `NEXT_PUBLIC_SOLANA_TOKEN_MINT_ADDRESS` matches your desired SPL token.
|
|
||||||
- **Incorrect decimals**: Ensure `NEXT_PUBLIC_SOLANA_TOKEN_DECIMALS` matches the token's actual decimal count.
|
|
||||||
- **Payment amount**: Adjust `NEXT_PUBLIC_SOLANA_PAYMENT_AMOUNT` to the desired payment amount.
|
|
||||||
|
|
||||||
### Laconic Registry Issues
|
### Laconic Registry Issues
|
||||||
|
|
||||||
- **Failed to create record**: Check that your REGISTRY_USER_KEY and REGISTRY_BOND_ID are correctly set.
|
- **Failed to create record**: Check that your REGISTRY_USER_KEY and REGISTRY_BOND_ID are correctly set.
|
||||||
|
@ -4,14 +4,14 @@
|
|||||||
|
|
||||||
### gor-deploy
|
### gor-deploy
|
||||||
|
|
||||||
* Clone the repo:
|
- Clone the repo:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git clone git@git.vdb.to:LaconicNetwork/gor-deploy.git
|
git clone git@git.vdb.to:LaconicNetwork/gor-deploy.git
|
||||||
cd gor-deploy/deploy
|
cd gor-deploy/deploy
|
||||||
```
|
```
|
||||||
|
|
||||||
* Build registry CLI image:
|
- Build registry CLI image:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker build -t cerc/laconic-registry-cli .
|
docker build -t cerc/laconic-registry-cli .
|
||||||
@ -19,13 +19,31 @@
|
|||||||
# Builds image cerc/laconic-registry-cli:latest
|
# Builds image cerc/laconic-registry-cli:latest
|
||||||
```
|
```
|
||||||
|
|
||||||
* Configure `userKey` and `bondId` in the [registry CLI config](./config.yml):
|
- Configure `userKey` and `bondId` in the [registry CLI config](./config.yml):
|
||||||
|
|
||||||
|
- User key should be of the account that owns the `laconic-deploy` authority (owner account address: `laconic1kwx2jm6vscz38qlyujvq6msujmk8l3zangqahs`)
|
||||||
|
- The bond should also be owned by same user (owned bond's ID: `230cfedda15e78edc8986dfcb870e1b618f65c56e38d2735476d2a8cb3f25e38`)
|
||||||
|
- If the authority is not available, follow [these steps to reserve a new authority](./publish-pricing.md#reserve-a-new-authority-optional)
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
nano config.yml
|
nano config.yml
|
||||||
```
|
```
|
||||||
|
|
||||||
* Add configuration for registry operations:
|
- This project requires pricing records for cost of deployment and cost of alnt to be published
|
||||||
|
|
||||||
|
- Check if these records are available by running following commands:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check if `lrn://laconic/pricing/webapp-deployment` is available
|
||||||
|
./laconic-cli.sh name resolve lrn://laconic/pricing/webapp-deployment
|
||||||
|
|
||||||
|
# Check if `lrn://laconic/pricing/alnt` is available
|
||||||
|
./laconic-cli.sh name resolve lrn://laconic/pricing/alnt
|
||||||
|
```
|
||||||
|
|
||||||
|
- If these records are not available, [follow these steps to publish them](./publish-pricing.md)
|
||||||
|
|
||||||
|
- Add configuration for registry operations:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cp .registry.env.example .registry.env
|
cp .registry.env.example .registry.env
|
||||||
@ -34,7 +52,7 @@
|
|||||||
nano .registry.env
|
nano .registry.env
|
||||||
```
|
```
|
||||||
|
|
||||||
* Add configuration for the app:
|
- Add configuration for the app:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
curl -s https://git.vdb.to/LaconicNetwork/gor-deploy/src/branch/main/.env.example -o .app.env
|
curl -s https://git.vdb.to/LaconicNetwork/gor-deploy/src/branch/main/.env.example -o .app.env
|
||||||
@ -43,11 +61,27 @@
|
|||||||
nano .app.env
|
nano .app.env
|
||||||
```
|
```
|
||||||
|
|
||||||
|
- Required environment variables:
|
||||||
|
|
||||||
|
Client-side (must be prefixed with NEXT_PUBLIC_):
|
||||||
|
- `NEXT_PUBLIC_SOLANA_RPC_URL` - The RPC URL for the Solana blockchain (SPL token transactions)
|
||||||
|
- `NEXT_PUBLIC_GORBAGANA_RPC_URL` - The RPC URL for the Gorbagana blockchain (native GOR transactions)
|
||||||
|
- `NEXT_PUBLIC_ENABLE_NATIVE_GOR_TRANSFER` - Enable native GOR token transfers (true/false)
|
||||||
|
- `NEXT_PUBLIC_SOLANA_TOKEN_RECIPIENT_ADDRESS` - The Solana address that will receive token payments
|
||||||
|
- `NEXT_PUBLIC_ALNT_COST_LRN` - LRN for ALNT token pricing
|
||||||
|
- `NEXT_PUBLIC_DEPLOYMENT_COST_LRN` - LRN for deployment cost pricing
|
||||||
|
- `NEXT_PUBLIC_DOMAIN_SUFFIX` - Suffix to append to DNS names in the UI (e.g. ".example.com")
|
||||||
|
|
||||||
|
Server-side:
|
||||||
|
- `REGISTRY_BOND_ID` - The bond ID to use for Laconic Registry records
|
||||||
|
- `REGISTRY_AUTHORITY` - The authority for Laconic Registry LRNs
|
||||||
|
- `REGISTRY_USER_KEY` - The private key for Laconic Registry transactions (also used for LNT transfers)
|
||||||
|
- `DEPLOYER_LRN` - The LRN of the deployer
|
||||||
|
|
||||||
## Run
|
## Run
|
||||||
|
|
||||||
### gor-deploy
|
- Deploy `gor-deploy` App:
|
||||||
|
|
||||||
* Deploy `gor-deploy` App:
|
|
||||||
```bash
|
```bash
|
||||||
# In gor-deploy/deploy dir
|
# In gor-deploy/deploy dir
|
||||||
docker run -it \
|
docker run -it \
|
||||||
@ -57,13 +91,13 @@
|
|||||||
./deploy.sh
|
./deploy.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
* Check deployment logs on deployer UI: <https://webapp-deployer-ui.apps.vaasl.io/>
|
- Check deployment logs on deployer UI: <https://webapp-deployer-ui.apps.vaasl.io/>
|
||||||
|
|
||||||
* Visit deployed app: <https://gor-deploy.apps.vaasl.io>
|
- Visit deployed app: <https://gor-deploy.apps.vaasl.io>
|
||||||
|
|
||||||
### remove deployment
|
### Remove deployment
|
||||||
|
|
||||||
* Remove deployment:
|
- Remove deployment:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# In gor-deploy/deploy dir
|
# In gor-deploy/deploy dir
|
||||||
|
50
deploy/laconic-cli.sh
Executable file
50
deploy/laconic-cli.sh
Executable file
@ -0,0 +1,50 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Laconic Registry CLI Docker wrapper script
|
||||||
|
# This script wraps the Docker command to run laconic registry CLI commands
|
||||||
|
# Run this script from the deploy directory
|
||||||
|
|
||||||
|
# Check if docker is available
|
||||||
|
if ! command -v docker &> /dev/null; then
|
||||||
|
echo "Error: Docker is not installed or not in PATH"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if the cerc/laconic-registry-cli image exists
|
||||||
|
if ! docker image inspect cerc/laconic-registry-cli &> /dev/null; then
|
||||||
|
echo "Error: cerc/laconic-registry-cli Docker image not found"
|
||||||
|
echo "Please build the image first: docker build -t cerc/laconic-registry-cli ."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Get current directory (should be deploy directory)
|
||||||
|
CURRENT_DIR="$(pwd)"
|
||||||
|
PROJECT_ROOT="$(dirname "$CURRENT_DIR")"
|
||||||
|
|
||||||
|
# Verify we're in the deploy directory
|
||||||
|
if [ ! -f "config.yml" ] || [ ! -f "laconic-cli.sh" ]; then
|
||||||
|
echo "Error: This script must be run from the deploy directory"
|
||||||
|
echo "Current directory: $CURRENT_DIR"
|
||||||
|
echo "Please cd to the deploy directory and run: ./laconic-cli.sh"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Set up volume mounts
|
||||||
|
DEPLOY_MOUNT="-v $CURRENT_DIR:/app/deploy"
|
||||||
|
OUT_MOUNT=""
|
||||||
|
|
||||||
|
# Create out directory if it doesn't exist and always mount it
|
||||||
|
if [ ! -d "out" ]; then
|
||||||
|
mkdir -p "out"
|
||||||
|
fi
|
||||||
|
OUT_MOUNT="-v $CURRENT_DIR/out:/app/out"
|
||||||
|
|
||||||
|
# Run the Docker command with processed arguments
|
||||||
|
docker run --rm \
|
||||||
|
--add-host=host.docker.internal:host-gateway \
|
||||||
|
$DEPLOY_MOUNT \
|
||||||
|
$OUT_MOUNT \
|
||||||
|
-w /app/deploy \
|
||||||
|
cerc/laconic-registry-cli \
|
||||||
|
laconic registry -c config.yml \
|
||||||
|
"$@"
|
147
deploy/publish-pricing.md
Normal file
147
deploy/publish-pricing.md
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
# publish-pricing
|
||||||
|
|
||||||
|
## Setup
|
||||||
|
|
||||||
|
- Clone the repo:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git clone git@git.vdb.to:LaconicNetwork/gor-deploy.git
|
||||||
|
cd gor-deploy/deploy
|
||||||
|
```
|
||||||
|
|
||||||
|
- Build the Docker container:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker build -t cerc/laconic-registry-cli .
|
||||||
|
|
||||||
|
# Builds image cerc/laconic-registry-cli:latest
|
||||||
|
```
|
||||||
|
|
||||||
|
- Configure `userKey` in the [registry CLI config](./config.yml):
|
||||||
|
|
||||||
|
NOTE: The `laconic` authority is required to set the published record names so the user key should be of the account that owns the `laconic` authority (owner account address: `laconic13maulvmjxnyx3g855vk0lsv5aptf3rpxskynef`). If you don't have an authority check [steps to reserve a new authority](#reserve-a-new-authority-optional)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
nano config.yml
|
||||||
|
```
|
||||||
|
|
||||||
|
## Publish Record and Set Record Name
|
||||||
|
|
||||||
|
Publishing record requires a bond with enough funds as rent is taken for each record from the bond every year
|
||||||
|
|
||||||
|
The rent amount taken is `1000000alnt` so maintaining a bond with about 10x the rent amount i.e `10000000alnt` is recommended
|
||||||
|
|
||||||
|
Make sure, the record names are under `laconic` authority
|
||||||
|
|
||||||
|
### Publish Record for Cost of alnt
|
||||||
|
|
||||||
|
- alnt price calculation (reference: <https://store.laconic.com>):
|
||||||
|
- Cost of 1 deployment is `12960` in terms of `alnt` or `5` in terms of `USD`
|
||||||
|
- Hence, cost of 1 `alnt` comes out be `0.000386 USD` rounded off to 6 decimals
|
||||||
|
|
||||||
|
- Publish the record:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./laconic-cli.sh record publish --filename records/alnt-pricing.yml --bond-id <bond-id>
|
||||||
|
```
|
||||||
|
|
||||||
|
- Get record info:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./laconic-cli.sh record get --id <record-id>
|
||||||
|
```
|
||||||
|
|
||||||
|
- Set record name for cost of alnt record:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./laconic-cli.sh name set lrn://laconic/pricing/alnt <record-id>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Publish Record for Cost of Deployment
|
||||||
|
|
||||||
|
- Publish the record:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./laconic-cli.sh record publish --filename records/webapp-deployment-pricing.yml --bond-id <bond-id>
|
||||||
|
```
|
||||||
|
|
||||||
|
- Get record info:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./laconic-cli.sh record get --id <record-id>
|
||||||
|
```
|
||||||
|
|
||||||
|
- Set record name for cost of deployment record
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./laconic-cli.sh name set lrn://laconic/pricing/webapp-deployment <record-id>
|
||||||
|
```
|
||||||
|
|
||||||
|
- Now you should be able to use these records in the app
|
||||||
|
|
||||||
|
- You can now continue with [steps to deploy the app](./README.md)
|
||||||
|
|
||||||
|
## Create Bond (optional)
|
||||||
|
|
||||||
|
- Create bond:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./laconic-cli.sh bond create --type alnt --quantity 10000000
|
||||||
|
```
|
||||||
|
|
||||||
|
- Get bond info:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./laconic-cli.sh bond get --id <bond-id>
|
||||||
|
```
|
||||||
|
|
||||||
|
## Reserve a New Authority (optional)
|
||||||
|
|
||||||
|
Below steps are used to reserve `laconic` authority
|
||||||
|
|
||||||
|
- Reserve authority:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./laconic-cli.sh authority reserve laconic
|
||||||
|
```
|
||||||
|
|
||||||
|
- After reserving authority, commit phase begins which lasts for 1 minute so please commit the bid following below steps within that time period
|
||||||
|
|
||||||
|
- Check authority info:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./laconic-cli.sh authority whois laconic
|
||||||
|
```
|
||||||
|
|
||||||
|
- Note down auction ID from authority info as it is required in next steps
|
||||||
|
|
||||||
|
- Get auction info:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./laconic-cli.sh auction get <auction-id>
|
||||||
|
```
|
||||||
|
|
||||||
|
- Commit an auction bid:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 5000000 alnt is the minimum bid amount for authority auction
|
||||||
|
|
||||||
|
./laconic-cli.sh auction bid commit <auction-id> 5000000 alnt
|
||||||
|
|
||||||
|
# Example file path inside container
|
||||||
|
Reveal file: /app/deploy/out/bafyreiay2rccax64yn4ljhvzvm3jkbebvzheyucuma5jlbpzpzd5i5gjuy.json
|
||||||
|
```
|
||||||
|
|
||||||
|
- The reveal phase starts as soon as commit phase ends and lasts for 1 minute so please reveal the bid within this time period
|
||||||
|
|
||||||
|
- Reveal bid:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./laconic-cli.sh auction bid reveal <auction-id> /app/deploy/out/<reaveal-file>.json
|
||||||
|
```
|
||||||
|
|
||||||
|
- Set authority bond after winning auction as it is required to use the published authority:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./laconic-cli.sh authority bond set laconic <bond-id>
|
||||||
|
```
|
6
deploy/records/alnt-pricing.yml
Normal file
6
deploy/records/alnt-pricing.yml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
record:
|
||||||
|
type: PricingRecord
|
||||||
|
for: "alnt"
|
||||||
|
amount: "0.000386"
|
||||||
|
currency: "USD"
|
||||||
|
version: 1.0.0
|
6
deploy/records/webapp-deployment-pricing.yml
Normal file
6
deploy/records/webapp-deployment-pricing.yml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
record:
|
||||||
|
type: PricingRecord
|
||||||
|
for: "webapp-deployment"
|
||||||
|
amount: "12960"
|
||||||
|
currency: "alnt"
|
||||||
|
version: 1.0.0
|
310
package-lock.json
generated
310
package-lock.json
generated
@ -25,6 +25,7 @@
|
|||||||
"react-dom": "^19.0.0"
|
"react-dom": "^19.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@cerc-io/laconic-registry-cli": "^0.2.9",
|
||||||
"@eslint/eslintrc": "^3",
|
"@eslint/eslintrc": "^3",
|
||||||
"@tailwindcss/postcss": "^4",
|
"@tailwindcss/postcss": "^4",
|
||||||
"@types/node": "^20",
|
"@types/node": "^20",
|
||||||
@ -515,72 +516,47 @@
|
|||||||
"node": ">=6.9.0"
|
"node": ">=6.9.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/template": {
|
"node_modules/@cerc-io/laconic-registry-cli": {
|
||||||
"version": "7.27.2",
|
"version": "0.2.10",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz",
|
"resolved": "https://git.vdb.to/api/packages/cerc-io/npm/%40cerc-io%2Flaconic-registry-cli/-/0.2.10/laconic-registry-cli-0.2.10.tgz",
|
||||||
"integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==",
|
"integrity": "sha512-rwrZhFgYZiMh2k+9E/aiyRhFLApydRUwclATb0f6hsFAkxARuaibHsJNy7eF2N/AQ4d6HAvpkXACJoVrGOppmw==",
|
||||||
"license": "MIT",
|
"dev": true,
|
||||||
"peer": true,
|
"license": "UNLICENSED",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/code-frame": "^7.27.1",
|
"@cerc-io/registry-sdk": "^0.2.11",
|
||||||
"@babel/parser": "^7.27.2",
|
"@cosmjs/stargate": "^0.32.2",
|
||||||
"@babel/types": "^7.27.1"
|
"fs-extra": "^10.1.0",
|
||||||
|
"js-yaml": "^3.14.1",
|
||||||
|
"lodash": "^4.17.21",
|
||||||
|
"lodash-clean": "^2.2.3",
|
||||||
|
"yargs": "^17.4.1"
|
||||||
},
|
},
|
||||||
"engines": {
|
"bin": {
|
||||||
"node": ">=6.9.0"
|
"laconic": "bin/laconic"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/traverse": {
|
"node_modules/@cerc-io/laconic-registry-cli/node_modules/argparse": {
|
||||||
"version": "7.28.0",
|
"version": "1.0.10",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.0.tgz",
|
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
|
||||||
"integrity": "sha512-mGe7UK5wWyh0bKRfupsUchrQGqvDbZDbKJw+kcRGSmdHVYrv+ltd0pnpDTVpiTqnaBru9iEvA8pz8W46v0Amwg==",
|
"integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/code-frame": "^7.27.1",
|
"sprintf-js": "~1.0.2"
|
||||||
"@babel/generator": "^7.28.0",
|
|
||||||
"@babel/helper-globals": "^7.28.0",
|
|
||||||
"@babel/parser": "^7.28.0",
|
|
||||||
"@babel/template": "^7.27.2",
|
|
||||||
"@babel/types": "^7.28.0",
|
|
||||||
"debug": "^4.3.1"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=6.9.0"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/traverse--for-generate-function-map": {
|
"node_modules/@cerc-io/laconic-registry-cli/node_modules/js-yaml": {
|
||||||
"name": "@babel/traverse",
|
"version": "3.14.1",
|
||||||
"version": "7.28.0",
|
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.0.tgz",
|
"integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
|
||||||
"integrity": "sha512-mGe7UK5wWyh0bKRfupsUchrQGqvDbZDbKJw+kcRGSmdHVYrv+ltd0pnpDTVpiTqnaBru9iEvA8pz8W46v0Amwg==",
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/code-frame": "^7.27.1",
|
"argparse": "^1.0.7",
|
||||||
"@babel/generator": "^7.28.0",
|
"esprima": "^4.0.0"
|
||||||
"@babel/helper-globals": "^7.28.0",
|
|
||||||
"@babel/parser": "^7.28.0",
|
|
||||||
"@babel/template": "^7.27.2",
|
|
||||||
"@babel/types": "^7.28.0",
|
|
||||||
"debug": "^4.3.1"
|
|
||||||
},
|
},
|
||||||
"engines": {
|
"bin": {
|
||||||
"node": ">=6.9.0"
|
"js-yaml": "bin/js-yaml.js"
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@babel/types": {
|
|
||||||
"version": "7.28.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.1.tgz",
|
|
||||||
"integrity": "sha512-x0LvFTekgSX+83TI28Y9wYPUfzrnl2aT5+5QLnO6v7mSJYtEEevuDRN0F0uSHRk1G1IWZC43o00Y0xDDrpBGPQ==",
|
|
||||||
"license": "MIT",
|
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
|
||||||
"@babel/helper-string-parser": "^7.27.1",
|
|
||||||
"@babel/helper-validator-identifier": "^7.27.1"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=6.9.0"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@cerc-io/registry-sdk": {
|
"node_modules/@cerc-io/registry-sdk": {
|
||||||
@ -5176,17 +5152,11 @@
|
|||||||
"url": "https://github.com/sponsors/epoberezkin"
|
"url": "https://github.com/sponsors/epoberezkin"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/anser": {
|
|
||||||
"version": "1.4.10",
|
|
||||||
"resolved": "https://registry.npmjs.org/anser/-/anser-1.4.10.tgz",
|
|
||||||
"integrity": "sha512-hCv9AqTQ8ycjpSd3upOJd7vFwW1JaoYQ7tpham03GJ1ca8/65rqn0RpaWpItOAd6ylW9wAw6luXYPJIyPFVOww==",
|
|
||||||
"license": "MIT",
|
|
||||||
"peer": true
|
|
||||||
},
|
|
||||||
"node_modules/ansi-regex": {
|
"node_modules/ansi-regex": {
|
||||||
"version": "5.0.1",
|
"version": "5.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
|
||||||
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
|
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
@ -6072,14 +6042,18 @@
|
|||||||
"integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA=="
|
"integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA=="
|
||||||
},
|
},
|
||||||
"node_modules/cliui": {
|
"node_modules/cliui": {
|
||||||
"version": "6.0.0",
|
"version": "8.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
|
||||||
"integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==",
|
"integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
|
||||||
|
"dev": true,
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"string-width": "^4.2.0",
|
"string-width": "^4.2.0",
|
||||||
"strip-ansi": "^6.0.0",
|
"strip-ansi": "^6.0.1",
|
||||||
"wrap-ansi": "^6.2.0"
|
"wrap-ansi": "^7.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/co": {
|
"node_modules/co": {
|
||||||
@ -6794,19 +6768,12 @@
|
|||||||
"version": "3.2.0",
|
"version": "3.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
|
||||||
"integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
|
"integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6"
|
"node": ">=6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/escape-html": {
|
|
||||||
"version": "1.0.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
|
|
||||||
"integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==",
|
|
||||||
"license": "MIT",
|
|
||||||
"peer": true
|
|
||||||
},
|
|
||||||
"node_modules/escape-string-regexp": {
|
"node_modules/escape-string-regexp": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
|
||||||
@ -7638,14 +7605,19 @@
|
|||||||
"node": ">= 6"
|
"node": ">= 6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/fresh": {
|
"node_modules/fs-extra": {
|
||||||
"version": "0.5.2",
|
"version": "10.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
|
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz",
|
||||||
"integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==",
|
"integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==",
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
"dependencies": {
|
||||||
|
"graceful-fs": "^4.2.0",
|
||||||
|
"jsonfile": "^6.0.1",
|
||||||
|
"universalify": "^2.0.0"
|
||||||
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 0.6"
|
"node": ">=12"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/fs.realpath": {
|
"node_modules/fs.realpath": {
|
||||||
@ -7705,20 +7677,11 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/gensync": {
|
|
||||||
"version": "1.0.0-beta.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
|
|
||||||
"integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
|
|
||||||
"license": "MIT",
|
|
||||||
"peer": true,
|
|
||||||
"engines": {
|
|
||||||
"node": ">=6.9.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/get-caller-file": {
|
"node_modules/get-caller-file": {
|
||||||
"version": "2.0.5",
|
"version": "2.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
|
||||||
"integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
|
"integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
|
||||||
|
"dev": true,
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "6.* || 8.* || >= 10.*"
|
"node": "6.* || 8.* || >= 10.*"
|
||||||
@ -8380,6 +8343,7 @@
|
|||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
|
||||||
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
|
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
@ -9017,6 +8981,19 @@
|
|||||||
"json5": "lib/cli.js"
|
"json5": "lib/cli.js"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/jsonfile": {
|
||||||
|
"version": "6.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
|
||||||
|
"integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"universalify": "^2.0.0"
|
||||||
|
},
|
||||||
|
"optionalDependencies": {
|
||||||
|
"graceful-fs": "^4.1.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/jsx-ast-utils": {
|
"node_modules/jsx-ast-utils": {
|
||||||
"version": "3.3.5",
|
"version": "3.3.5",
|
||||||
"resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz",
|
"resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz",
|
||||||
@ -9484,6 +9461,16 @@
|
|||||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
||||||
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
|
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
|
||||||
},
|
},
|
||||||
|
"node_modules/lodash-clean": {
|
||||||
|
"version": "2.2.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/lodash-clean/-/lodash-clean-2.2.3.tgz",
|
||||||
|
"integrity": "sha512-ioRhn/L0NNKq220nba58FPvjZ+bTdlUCb37+mhlDe4kzIzuPC/prUHLwDM9izeicr/rcnWrn0EanzNxhAbo8oA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"lodash": "^4.17.21"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/lodash.merge": {
|
"node_modules/lodash.merge": {
|
||||||
"version": "4.6.2",
|
"version": "4.6.2",
|
||||||
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
|
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
|
||||||
@ -11124,17 +11111,12 @@
|
|||||||
"version": "2.1.1",
|
"version": "2.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
|
||||||
"integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
|
"integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/require-main-filename": {
|
|
||||||
"version": "2.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz",
|
|
||||||
"integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==",
|
|
||||||
"license": "ISC"
|
|
||||||
},
|
|
||||||
"node_modules/resolve": {
|
"node_modules/resolve": {
|
||||||
"version": "1.22.10",
|
"version": "1.22.10",
|
||||||
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz",
|
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz",
|
||||||
@ -11940,6 +11922,7 @@
|
|||||||
"version": "4.2.3",
|
"version": "4.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
|
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
|
||||||
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
|
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"emoji-regex": "^8.0.0",
|
"emoji-regex": "^8.0.0",
|
||||||
@ -11954,6 +11937,7 @@
|
|||||||
"version": "8.0.0",
|
"version": "8.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
|
||||||
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
|
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
|
||||||
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/string.prototype.includes": {
|
"node_modules/string.prototype.includes": {
|
||||||
@ -12067,6 +12051,7 @@
|
|||||||
"version": "6.0.1",
|
"version": "6.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
|
||||||
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
|
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ansi-regex": "^5.0.1"
|
"ansi-regex": "^5.0.1"
|
||||||
@ -12518,14 +12503,14 @@
|
|||||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz",
|
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz",
|
||||||
"integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw=="
|
"integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw=="
|
||||||
},
|
},
|
||||||
"node_modules/unpipe": {
|
"node_modules/universalify": {
|
||||||
"version": "1.0.0",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz",
|
||||||
"integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==",
|
"integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==",
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 0.8"
|
"node": ">= 10.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/unrs-resolver": {
|
"node_modules/unrs-resolver": {
|
||||||
@ -12800,9 +12785,10 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/wrap-ansi": {
|
"node_modules/wrap-ansi": {
|
||||||
"version": "6.2.0",
|
"version": "7.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
|
||||||
"integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
|
"integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ansi-styles": "^4.0.0",
|
"ansi-styles": "^4.0.0",
|
||||||
@ -12810,7 +12796,10 @@
|
|||||||
"strip-ansi": "^6.0.0"
|
"strip-ansi": "^6.0.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=8"
|
"node": ">=10"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/chalk/wrap-ansi?sponsor=1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/wrappy": {
|
"node_modules/wrappy": {
|
||||||
@ -12862,103 +12851,42 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/y18n": {
|
"node_modules/y18n": {
|
||||||
"version": "4.0.3",
|
"version": "5.0.8",
|
||||||
"resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
|
||||||
"integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==",
|
"integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
|
||||||
"license": "ISC"
|
"dev": true,
|
||||||
},
|
|
||||||
"node_modules/yallist": {
|
|
||||||
"version": "3.1.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
|
|
||||||
"integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
|
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"peer": true
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"node_modules/yargs": {
|
"node_modules/yargs": {
|
||||||
"version": "15.4.1",
|
"version": "17.7.2",
|
||||||
"resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
|
||||||
"integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==",
|
"integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"cliui": "^6.0.0",
|
"cliui": "^8.0.1",
|
||||||
"decamelize": "^1.2.0",
|
"escalade": "^3.1.1",
|
||||||
"find-up": "^4.1.0",
|
"get-caller-file": "^2.0.5",
|
||||||
"get-caller-file": "^2.0.1",
|
|
||||||
"require-directory": "^2.1.1",
|
"require-directory": "^2.1.1",
|
||||||
"require-main-filename": "^2.0.0",
|
"string-width": "^4.2.3",
|
||||||
"set-blocking": "^2.0.0",
|
"y18n": "^5.0.5",
|
||||||
"string-width": "^4.2.0",
|
"yargs-parser": "^21.1.1"
|
||||||
"which-module": "^2.0.0",
|
|
||||||
"y18n": "^4.0.0",
|
|
||||||
"yargs-parser": "^18.1.2"
|
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=8"
|
"node": ">=12"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/yargs-parser": {
|
"node_modules/yargs-parser": {
|
||||||
"version": "18.1.3",
|
"version": "21.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
|
||||||
"integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==",
|
"integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
|
||||||
|
"dev": true,
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
|
||||||
"camelcase": "^5.0.0",
|
|
||||||
"decamelize": "^1.2.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6"
|
"node": ">=12"
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/yargs/node_modules/find-up": {
|
|
||||||
"version": "4.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
|
|
||||||
"integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"locate-path": "^5.0.0",
|
|
||||||
"path-exists": "^4.0.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=8"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/yargs/node_modules/locate-path": {
|
|
||||||
"version": "5.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
|
|
||||||
"integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"p-locate": "^4.1.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=8"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/yargs/node_modules/p-limit": {
|
|
||||||
"version": "2.3.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
|
|
||||||
"integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"p-try": "^2.0.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=6"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"url": "https://github.com/sponsors/sindresorhus"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/yargs/node_modules/p-locate": {
|
|
||||||
"version": "4.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
|
|
||||||
"integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"p-limit": "^2.2.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=8"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/yocto-queue": {
|
"node_modules/yocto-queue": {
|
||||||
|
@ -6,7 +6,8 @@
|
|||||||
"dev": "next dev",
|
"dev": "next dev",
|
||||||
"build": "next build",
|
"build": "next build",
|
||||||
"start": "next start",
|
"start": "next start",
|
||||||
"lint": "next lint"
|
"lint": "next lint",
|
||||||
|
"laconic": "laconic registry -c deploy/config.yml"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@cerc-io/registry-sdk": "^0.2.11",
|
"@cerc-io/registry-sdk": "^0.2.11",
|
||||||
@ -28,6 +29,7 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/eslintrc": "^3",
|
"@eslint/eslintrc": "^3",
|
||||||
"@tailwindcss/postcss": "^4",
|
"@tailwindcss/postcss": "^4",
|
||||||
|
"@cerc-io/laconic-registry-cli": "^0.2.9",
|
||||||
"@types/node": "^20",
|
"@types/node": "^20",
|
||||||
"@types/react": "^19",
|
"@types/react": "^19",
|
||||||
"@types/react-dom": "^19",
|
"@types/react-dom": "^19",
|
||||||
|
@ -3,16 +3,16 @@ import { NextRequest, NextResponse } from 'next/server';
|
|||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import assert from 'assert';
|
import assert from 'assert';
|
||||||
|
|
||||||
import { GasPrice } from '@cosmjs/stargate';
|
|
||||||
import { Connection } from '@solana/web3.js';
|
import { Connection } from '@solana/web3.js';
|
||||||
import { DENOM as ALNT_DENOM } from '@cerc-io/registry-sdk';
|
|
||||||
|
|
||||||
import { verifyUnusedSolanaPayment } from '@/utils/solana-verify';
|
import { verifyUnusedSolanaPayment } from '@/utils/solana-verify';
|
||||||
import { transferLNTTokens } from '@/services/laconic-transfer';
|
import { transferLNTTokens } from '@/services/laconic-transfer';
|
||||||
import { getRegistry, getRegistryConfig } from '@/config';
|
import { getRegistry, getRegistryConfig } from '@/config';
|
||||||
import { getRequiredTokenInfo, RequiredTokenInfo } from '@/services/jupiter-price';
|
import { getRequiredTokenInfo, RequiredTokenInfo } from '@/services/jupiter-price';
|
||||||
import { IS_NAT_GOR_TRANSFER_ENABLED, SOLANA_GOR_MINT_ADDRESS } from '@/constants/payments';
|
import { SOLANA_GOR_MINT_ADDRESS } from '@/constants/payments';
|
||||||
import { PaymentMethod } from '@/types';
|
import { PaymentMethod } from '@/types';
|
||||||
|
import { getCostOfDeployment } from '@/services/registry';
|
||||||
|
import { IS_NAT_GOR_TRANSFER_ENABLED } from '@/utils/gorbagana';
|
||||||
|
|
||||||
assert(process.env.NEXT_PUBLIC_SOLANA_RPC_URL, 'SOLANA_RPC_URL is required');
|
assert(process.env.NEXT_PUBLIC_SOLANA_RPC_URL, 'SOLANA_RPC_URL is required');
|
||||||
assert(!IS_NAT_GOR_TRANSFER_ENABLED || process.env.NEXT_PUBLIC_GORBAGANA_RPC_URL, 'GORBAGANA_RPC_URL is required when NAT GOR transfer is enabled');
|
assert(!IS_NAT_GOR_TRANSFER_ENABLED || process.env.NEXT_PUBLIC_GORBAGANA_RPC_URL, 'GORBAGANA_RPC_URL is required when NAT GOR transfer is enabled');
|
||||||
@ -215,14 +215,10 @@ export async function POST(request: NextRequest) {
|
|||||||
}, { status: 400 });
|
}, { status: 400 });
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify Solana payment based on method
|
// Verify Solana payment
|
||||||
console.log(`Step 0: Verifying Solana ${paymentMethod} payment...`);
|
console.log('Step 0: Verifying Solana token payment...');
|
||||||
|
|
||||||
|
|
||||||
// Calculate expected token amount based on current price
|
|
||||||
let requiredTokenInfo: RequiredTokenInfo;
|
let requiredTokenInfo: RequiredTokenInfo;
|
||||||
|
const targetUsdAmount = await getCostOfDeployment();
|
||||||
const targetUsdAmount = parseFloat(process.env.NEXT_PUBLIC_SOLANA_PAYMENT_AMOUNT_USD!);
|
|
||||||
const mintAddress = process.env.NEXT_PUBLIC_SOLANA_TOKEN_MINT_ADDRESS!;
|
const mintAddress = process.env.NEXT_PUBLIC_SOLANA_TOKEN_MINT_ADDRESS!;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -284,9 +280,9 @@ export async function POST(request: NextRequest) {
|
|||||||
|
|
||||||
// Validate required environment variables for Solana payments
|
// Validate required environment variables for Solana payments
|
||||||
const requiredEnvVars = [
|
const requiredEnvVars = [
|
||||||
'REGISTRY_CHAIN_ID',
|
'NEXT_PUBLIC_REGISTRY_CHAIN_ID',
|
||||||
'REGISTRY_GQL_ENDPOINT',
|
'NEXT_PUBLIC_REGISTRY_GQL_ENDPOINT',
|
||||||
'REGISTRY_RPC_ENDPOINT',
|
'NEXT_PUBLIC_REGISTRY_RPC_ENDPOINT',
|
||||||
'REGISTRY_BOND_ID',
|
'REGISTRY_BOND_ID',
|
||||||
'REGISTRY_AUTHORITY',
|
'REGISTRY_AUTHORITY',
|
||||||
'REGISTRY_USER_KEY', // This is the same as the prefilled account for LNT transfers
|
'REGISTRY_USER_KEY', // This is the same as the prefilled account for LNT transfers
|
||||||
@ -354,10 +350,6 @@ export async function POST(request: NextRequest) {
|
|||||||
|
|
||||||
const deployerLrn = process.env.DEPLOYER_LRN!;
|
const deployerLrn = process.env.DEPLOYER_LRN!;
|
||||||
|
|
||||||
// Create Registry client instance
|
|
||||||
const gasPrice = GasPrice.fromString(config.fee.gasPrice + ALNT_DENOM);
|
|
||||||
console.log('Using manual gas price:', gasPrice);
|
|
||||||
|
|
||||||
const registry = getRegistry()
|
const registry = getRegistry()
|
||||||
|
|
||||||
// Create LRN for the application with commit hash
|
// Create LRN for the application with commit hash
|
||||||
|
@ -10,13 +10,21 @@ import { BackpackWalletName } from '@solana/wallet-adapter-backpack';
|
|||||||
import URLForm from '@/components/URLForm';
|
import URLForm from '@/components/URLForm';
|
||||||
import StatusDisplay from '@/components/StatusDisplay';
|
import StatusDisplay from '@/components/StatusDisplay';
|
||||||
import { createApplicationDeploymentRequest } from '@/services/registry';
|
import { createApplicationDeploymentRequest } from '@/services/registry';
|
||||||
import { IS_NAT_GOR_TRANSFER_ENABLED, PAYMENT_METHOD_LABELS } from '@/constants/payments';
|
import { PAYMENT_METHOD_LABELS } from '@/constants/payments';
|
||||||
import { usePaymentMethod } from '@/contexts/PaymentMethodContext';
|
import { usePaymentMethod } from '@/contexts/PaymentMethodContext';
|
||||||
import { PaymentMethod } from '@/types';
|
import { PaymentMethod } from '@/types';
|
||||||
|
import { IS_NAT_GOR_TRANSFER_ENABLED } from '@/utils/gorbagana';
|
||||||
|
|
||||||
// Dynamically import components to avoid SSR issues with browser APIs
|
// Dynamically import components to avoid SSR issues with browser APIs
|
||||||
const PaymentModal = dynamic(() => import('@/components/PaymentModal'), { ssr: false });
|
const PaymentModal = dynamic(() => import('@/components/PaymentModal'), { ssr: false });
|
||||||
|
|
||||||
|
// Use following curl request to get Gorbagana chain genesis hash:
|
||||||
|
// curl https://rpc.gorbagana.wtf \
|
||||||
|
// -X POST \
|
||||||
|
// -H "Content-Type: application/json" \
|
||||||
|
// --data '{"jsonrpc":"2.0","id":1,"method":"getGenesisHash"}'
|
||||||
|
//
|
||||||
|
// RPC endpoint reference: https://docs.gorbagana.wtf/testnet-v2-devnet.html
|
||||||
const GORBAGANA_GENESIS_HASH = '533uBE9RRquhTBqEX58oV52FdTTsReMdAvaUvP6hNjsn';
|
const GORBAGANA_GENESIS_HASH = '533uBE9RRquhTBqEX58oV52FdTTsReMdAvaUvP6hNjsn';
|
||||||
|
|
||||||
export default function Home() {
|
export default function Home() {
|
||||||
|
@ -9,8 +9,10 @@ import { useConnection, useWallet } from '@solana/wallet-adapter-react';
|
|||||||
import { sendSolanaPayment } from '@/services/solana';
|
import { sendSolanaPayment } from '@/services/solana';
|
||||||
import { getRequiredTokenInfo, RequiredTokenInfo } from '@/services/jupiter-price';
|
import { getRequiredTokenInfo, RequiredTokenInfo } from '@/services/jupiter-price';
|
||||||
import { PaymentMethod, PaymentModalProps, PaymentRequest } from '@/types';
|
import { PaymentMethod, PaymentModalProps, PaymentRequest } from '@/types';
|
||||||
import { IS_NAT_GOR_TRANSFER_ENABLED, PAYMENT_METHOD_LABELS, SOLANA_GOR_MINT_ADDRESS } from '@/constants/payments';
|
import { PAYMENT_METHOD_LABELS, SOLANA_GOR_MINT_ADDRESS } from '@/constants/payments';
|
||||||
import { usePaymentMethod } from '@/contexts/PaymentMethodContext';
|
import { usePaymentMethod } from '@/contexts/PaymentMethodContext';
|
||||||
|
import { getCostOfDeployment } from '@/services/registry';
|
||||||
|
import { IS_NAT_GOR_TRANSFER_ENABLED } from '@/utils/gorbagana';
|
||||||
|
|
||||||
assert(!IS_NAT_GOR_TRANSFER_ENABLED || process.env.NEXT_PUBLIC_GORBAGANA_RPC_URL, 'GORBAGANA_RPC_URL is required when NAT GOR transfer is enabled');
|
assert(!IS_NAT_GOR_TRANSFER_ENABLED || process.env.NEXT_PUBLIC_GORBAGANA_RPC_URL, 'GORBAGANA_RPC_URL is required when NAT GOR transfer is enabled');
|
||||||
|
|
||||||
@ -23,28 +25,32 @@ export default function PaymentModal({
|
|||||||
onPaymentComplete,
|
onPaymentComplete,
|
||||||
}: PaymentModalProps) {
|
}: PaymentModalProps) {
|
||||||
const { selectedPaymentMethod: paymentMethod } = usePaymentMethod();
|
const { selectedPaymentMethod: paymentMethod } = usePaymentMethod();
|
||||||
|
|
||||||
const { connection: solanaConnection } = useConnection();
|
const { connection: solanaConnection } = useConnection();
|
||||||
|
const { wallet, publicKey } = useWallet();
|
||||||
|
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const [error, setError] = useState('');
|
const [error, setError] = useState('');
|
||||||
const [tokenAmount, setTokenAmount] = useState<number>(0);
|
const [tokenAmount, setTokenAmount] = useState<number>(0);
|
||||||
const [tokenDecimals, setTokenDecimals] = useState<number>(6); // Default fallback
|
const [tokenDecimals, setTokenDecimals] = useState<number>(6); // Default fallback
|
||||||
const [loadingPrice, setLoadingPrice] = useState(false);
|
const [loadingPrice, setLoadingPrice] = useState(true);
|
||||||
|
const [deploymentCost, setDeploymentCost] = useState<number | null>(null);
|
||||||
|
|
||||||
const { wallet, publicKey } = useWallet();
|
useEffect(() => {
|
||||||
|
const getDeploymentCostInfo = async () => {
|
||||||
|
const cost = await getCostOfDeployment();
|
||||||
|
|
||||||
|
setDeploymentCost(cost);
|
||||||
|
}
|
||||||
|
|
||||||
|
getDeploymentCostInfo();
|
||||||
|
}, []);
|
||||||
|
|
||||||
// Get configuration from environment variables
|
|
||||||
const targetUsdAmount = parseFloat(process.env.NEXT_PUBLIC_SOLANA_PAYMENT_AMOUNT_USD!);
|
|
||||||
const mintAddress = process.env.NEXT_PUBLIC_SOLANA_TOKEN_MINT_ADDRESS!;
|
const mintAddress = process.env.NEXT_PUBLIC_SOLANA_TOKEN_MINT_ADDRESS!;
|
||||||
const tokenSymbol = process.env.NEXT_PUBLIC_SOLANA_TOKEN_SYMBOL;
|
const tokenSymbol = process.env.NEXT_PUBLIC_SOLANA_TOKEN_SYMBOL;
|
||||||
|
|
||||||
// Fetch payment amount based on USD price for both payment methods
|
// Fetch payment amount based on USD price for both payment methods
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!isOpen || !paymentMethod) {
|
if (!isOpen || !deploymentCost || !paymentMethod) return;
|
||||||
setLoadingPrice(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const fetchPaymentAmount = async () => {
|
const fetchPaymentAmount = async () => {
|
||||||
setLoadingPrice(true);
|
setLoadingPrice(true);
|
||||||
@ -54,10 +60,10 @@ export default function PaymentModal({
|
|||||||
let requiredTokenInfo: RequiredTokenInfo
|
let requiredTokenInfo: RequiredTokenInfo
|
||||||
if (paymentMethod === PaymentMethod.NAT_GOR) {
|
if (paymentMethod === PaymentMethod.NAT_GOR) {
|
||||||
// Fetch native GOR amount using solana GOR token price
|
// Fetch native GOR amount using solana GOR token price
|
||||||
requiredTokenInfo = await getRequiredTokenInfo(targetUsdAmount, SOLANA_GOR_MINT_ADDRESS);
|
requiredTokenInfo = await getRequiredTokenInfo(deploymentCost, SOLANA_GOR_MINT_ADDRESS);
|
||||||
} else if (paymentMethod === PaymentMethod.SPL_TOKEN) {
|
} else if (paymentMethod === PaymentMethod.SPL_TOKEN) {
|
||||||
// Fetch SPL token amount using token mint price
|
// Fetch SPL token amount using token mint price
|
||||||
requiredTokenInfo = await getRequiredTokenInfo(targetUsdAmount, mintAddress);
|
requiredTokenInfo = await getRequiredTokenInfo(deploymentCost, mintAddress);
|
||||||
} else {
|
} else {
|
||||||
setError('Invalid payment method');
|
setError('Invalid payment method');
|
||||||
return;
|
return;
|
||||||
@ -74,7 +80,7 @@ export default function PaymentModal({
|
|||||||
};
|
};
|
||||||
|
|
||||||
fetchPaymentAmount();
|
fetchPaymentAmount();
|
||||||
}, [isOpen, paymentMethod, targetUsdAmount, mintAddress]);
|
}, [isOpen, paymentMethod, deploymentCost, mintAddress]);
|
||||||
|
|
||||||
// Initialize state when modal opens
|
// Initialize state when modal opens
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -184,19 +190,32 @@ export default function PaymentModal({
|
|||||||
</label>
|
</label>
|
||||||
<div className="space-y-3">
|
<div className="space-y-3">
|
||||||
<div className="relative">
|
<div className="relative">
|
||||||
<input
|
{loadingPrice ? (
|
||||||
type="text"
|
<div className="w-full p-3 rounded-md flex items-center" style={{
|
||||||
value={targetUsdAmount}
|
background: 'var(--muted-light)',
|
||||||
disabled={true}
|
|
||||||
className="w-full p-3 pr-12 rounded-md"
|
|
||||||
style={{
|
|
||||||
background: 'var(--card-bg)',
|
|
||||||
border: '1px solid var(--input-border)',
|
border: '1px solid var(--input-border)',
|
||||||
color: 'var(--foreground)',
|
color: 'var(--muted)'
|
||||||
opacity: '0.7'
|
}}>
|
||||||
}}
|
<svg className="animate-spin h-4 w-4 mr-2" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
|
||||||
readOnly
|
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4"></circle>
|
||||||
/>
|
<path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
value={`$${deploymentCost ? deploymentCost.toPrecision(2) : null}`}
|
||||||
|
disabled={true}
|
||||||
|
className="w-full p-3 pr-12 rounded-md"
|
||||||
|
style={{
|
||||||
|
background: 'var(--card-bg)',
|
||||||
|
border: '1px solid var(--input-border)',
|
||||||
|
color: 'var(--foreground)',
|
||||||
|
opacity: '0.7'
|
||||||
|
}}
|
||||||
|
readOnly
|
||||||
|
/>
|
||||||
|
)}
|
||||||
<div className="absolute inset-y-0 right-0 flex items-center pr-3 pointer-events-none">
|
<div className="absolute inset-y-0 right-0 flex items-center pr-3 pointer-events-none">
|
||||||
<span className="text-sm font-medium" style={{ color: 'var(--muted)' }}>USD</span>
|
<span className="text-sm font-medium" style={{ color: 'var(--muted)' }}>USD</span>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,30 +1,43 @@
|
|||||||
import { Registry, DENOM as ALNT_DENOM } from '@cerc-io/registry-sdk';
|
import { DENOM as ALNT_DENOM, Registry } from '@cerc-io/registry-sdk';
|
||||||
import { GasPrice } from '@cosmjs/stargate';
|
|
||||||
|
|
||||||
import { RegistryConfig } from '../types';
|
import { RegistryConfig } from '../types';
|
||||||
|
import { GasPrice } from '@cosmjs/stargate';
|
||||||
|
|
||||||
let registryInstance: Registry | null = null;
|
let registryInstance: Registry | null = null;
|
||||||
|
|
||||||
|
|
||||||
export const getRegistry = (): Registry => {
|
export const getRegistry = (): Registry => {
|
||||||
if (!registryInstance) {
|
if (!registryInstance) {
|
||||||
const config = getRegistryConfig();
|
const config = getClientRegistryConfig();
|
||||||
const gasPrice = GasPrice.fromString(config.fee.gasPrice + ALNT_DENOM);
|
const REGISTRY_GAS_PRICE = process.env.REGISTRY_GAS_PRICE;
|
||||||
|
const gasPrice = REGISTRY_GAS_PRICE ? GasPrice.fromString( REGISTRY_GAS_PRICE + ALNT_DENOM) : undefined;
|
||||||
|
|
||||||
registryInstance = new Registry(
|
registryInstance = new Registry(
|
||||||
config.gqlEndpoint,
|
config.gqlEndpoint,
|
||||||
config.rpcEndpoint,
|
config.rpcEndpoint,
|
||||||
{ chainId: config.chainId, gasPrice }
|
{
|
||||||
|
chainId: config.chainId,
|
||||||
|
gasPrice,
|
||||||
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return registryInstance;
|
return registryInstance;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getClientRegistryConfig = () => {
|
||||||
|
return {
|
||||||
|
chainId: process.env.NEXT_PUBLIC_REGISTRY_CHAIN_ID!,
|
||||||
|
rpcEndpoint: process.env.NEXT_PUBLIC_REGISTRY_RPC_ENDPOINT!,
|
||||||
|
gqlEndpoint: process.env.NEXT_PUBLIC_REGISTRY_GQL_ENDPOINT!,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
export const getRegistryConfig = (): RegistryConfig => {
|
export const getRegistryConfig = (): RegistryConfig => {
|
||||||
// Validate required environment variables
|
// Validate required environment variables
|
||||||
const requiredEnvVars = [
|
const requiredEnvVars = [
|
||||||
'REGISTRY_CHAIN_ID',
|
'NEXT_PUBLIC_REGISTRY_CHAIN_ID',
|
||||||
'REGISTRY_GQL_ENDPOINT',
|
'NEXT_PUBLIC_REGISTRY_GQL_ENDPOINT',
|
||||||
'REGISTRY_RPC_ENDPOINT',
|
'NEXT_PUBLIC_REGISTRY_RPC_ENDPOINT',
|
||||||
'REGISTRY_BOND_ID',
|
'REGISTRY_BOND_ID',
|
||||||
'REGISTRY_AUTHORITY',
|
'REGISTRY_AUTHORITY',
|
||||||
'REGISTRY_USER_KEY'
|
'REGISTRY_USER_KEY'
|
||||||
@ -37,14 +50,11 @@ export const getRegistryConfig = (): RegistryConfig => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
chainId: process.env.REGISTRY_CHAIN_ID!,
|
chainId: process.env.NEXT_PUBLIC_REGISTRY_CHAIN_ID!,
|
||||||
rpcEndpoint: process.env.REGISTRY_RPC_ENDPOINT!,
|
rpcEndpoint: process.env.NEXT_PUBLIC_REGISTRY_RPC_ENDPOINT!,
|
||||||
gqlEndpoint: process.env.REGISTRY_GQL_ENDPOINT!,
|
gqlEndpoint: process.env.NEXT_PUBLIC_REGISTRY_GQL_ENDPOINT!,
|
||||||
bondId: process.env.REGISTRY_BOND_ID!,
|
bondId: process.env.REGISTRY_BOND_ID!,
|
||||||
authority: process.env.REGISTRY_AUTHORITY!,
|
authority: process.env.REGISTRY_AUTHORITY!,
|
||||||
privateKey: process.env.REGISTRY_USER_KEY!,
|
privateKey: process.env.REGISTRY_USER_KEY!,
|
||||||
fee: {
|
|
||||||
gasPrice: process.env.REGISTRY_GAS_PRICE || '0.001',
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -7,5 +7,3 @@ export const PAYMENT_METHOD_LABELS: Record<PaymentMethod, string> = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const SOLANA_GOR_MINT_ADDRESS = '71Jvq4Epe2FCJ7JFSF7jLXdNk1Wy4Bhqd9iL6bEFELvg';
|
export const SOLANA_GOR_MINT_ADDRESS = '71Jvq4Epe2FCJ7JFSF7jLXdNk1Wy4Bhqd9iL6bEFELvg';
|
||||||
|
|
||||||
export const IS_NAT_GOR_TRANSFER_ENABLED = process.env.NEXT_PUBLIC_ENABLE_NATIVE_GOR_TRANSFER === "true";
|
|
||||||
|
@ -86,7 +86,6 @@ const getAccount = async (accountPrivateKey: string): Promise<Account> => {
|
|||||||
return account;
|
return account;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const sendTokensToAccount = async (
|
const sendTokensToAccount = async (
|
||||||
senderPrivateKey: string,
|
senderPrivateKey: string,
|
||||||
receiverAddress: string,
|
receiverAddress: string,
|
||||||
|
@ -1,5 +1,13 @@
|
|||||||
import { CreateRecordResponse } from '../types';
|
import assert from 'assert';
|
||||||
import { PaymentMethod } from '../types';
|
|
||||||
|
import { getRegistry } from '@/config';
|
||||||
|
import { CreateRecordResponse, PricingRecordAttributes, PaymentMethod } from '../types';
|
||||||
|
|
||||||
|
assert(process.env.NEXT_PUBLIC_DEPLOYMENT_COST_LRN, 'DEPLOYMENT_COST_LRN is required');
|
||||||
|
assert(process.env.NEXT_PUBLIC_ALNT_COST_LRN, 'ALNT_COST_LRN is required');
|
||||||
|
|
||||||
|
const DEPLOYMENT_COST_LRN = process.env.NEXT_PUBLIC_DEPLOYMENT_COST_LRN;
|
||||||
|
const ALNT_COST_LRN = process.env.NEXT_PUBLIC_ALNT_COST_LRN;
|
||||||
|
|
||||||
export const createApplicationDeploymentRequest = async (
|
export const createApplicationDeploymentRequest = async (
|
||||||
url: string,
|
url: string,
|
||||||
@ -51,3 +59,33 @@ export const createApplicationDeploymentRequest = async (
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const resolvePricingRecordLrns = async (lrns: string[]): Promise<PricingRecordAttributes[]> => {
|
||||||
|
const registry = getRegistry();
|
||||||
|
const result = await registry.resolveNames(lrns);
|
||||||
|
const pricingRecordsAttributes: PricingRecordAttributes[] = result.map((record: any) => {
|
||||||
|
return record.attributes
|
||||||
|
});
|
||||||
|
|
||||||
|
return pricingRecordsAttributes;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getCostOfDeployment = async (): Promise<number> => {
|
||||||
|
const resolvedRecords = await resolvePricingRecordLrns([ALNT_COST_LRN, DEPLOYMENT_COST_LRN]);
|
||||||
|
console.log('resolvedRecords:', resolvedRecords);
|
||||||
|
|
||||||
|
// Find the ALNT price record (USD per ALNT)
|
||||||
|
const alntPriceRecord = resolvedRecords[0];
|
||||||
|
// Find the deployment cost record (ALNT cost for webapp-deployment)
|
||||||
|
const deploymentCostRecord = resolvedRecords[1];
|
||||||
|
|
||||||
|
if (!alntPriceRecord || !deploymentCostRecord) {
|
||||||
|
throw new Error('Required pricing records not found');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert strings to numbers for calculation
|
||||||
|
const alntPriceUsd = parseFloat(alntPriceRecord.amount); // USD per ALNT
|
||||||
|
const deploymentCostAlnt = parseFloat(deploymentCostRecord.amount); // ALNT required
|
||||||
|
|
||||||
|
// Calculate deployment cost in USD: (ALNT required) * (USD per ALNT)
|
||||||
|
return deploymentCostAlnt * alntPriceUsd;
|
||||||
|
}
|
||||||
|
@ -10,9 +10,6 @@ export interface RegistryConfig {
|
|||||||
bondId: string;
|
bondId: string;
|
||||||
authority: string;
|
authority: string;
|
||||||
privateKey: string;
|
privateKey: string;
|
||||||
fee: {
|
|
||||||
gasPrice: string;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface CreateRecordResponse {
|
export interface CreateRecordResponse {
|
||||||
@ -53,3 +50,11 @@ export interface LaconicTransferResult {
|
|||||||
transactionHash?: string;
|
transactionHash?: string;
|
||||||
error?: string;
|
error?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface PricingRecordAttributes {
|
||||||
|
amount: string;
|
||||||
|
currency: string;
|
||||||
|
for: string;
|
||||||
|
type: string;
|
||||||
|
version: string;
|
||||||
|
}
|
||||||
|
1
src/utils/gorbagana.ts
Normal file
1
src/utils/gorbagana.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export const IS_NAT_GOR_TRANSFER_ENABLED = process.env.NEXT_PUBLIC_ENABLE_NATIVE_GOR_TRANSFER === "true";
|
Loading…
Reference in New Issue
Block a user