├── .devcontainer └── devcontainer.json ├── .dockerignore ├── .editorconfig ├── .gitattributes ├── .github ├── CODEOWNERS ├── FUNDING.yml └── workflows │ ├── build.yml │ ├── dockerhub.yml │ └── release.yml ├── .gitignore ├── .jitpack.yml ├── .vscode └── settings.json ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── DB_DEV.md ├── DB_SETUP_MARIADB.md ├── DB_SETUP_POSTGRESQL.md ├── DB_SETUP_SQLITE.md ├── Dockerfile ├── LICENSE.txt ├── README.md ├── SSL_SETUP.md ├── build.gradle ├── checkstyle.xml ├── ci ├── getLatestPhoenixVersion.js ├── updateClassic.sh └── updatePhoenix.sh ├── conf ├── junit │ └── node-default.properties ├── logging-default.properties ├── mainnet │ ├── node.h2.properties │ ├── node.mariadb.properties │ ├── node.postgres.properties │ └── node.sqlite.properties ├── mock │ ├── node-default.properties │ ├── node.properties │ └── node.sqlite-mock.properties ├── node-default.properties └── testnet │ ├── node.h2.properties │ ├── node.mariadb.properties │ ├── node.postgres.properties │ └── node.sqlite.properties ├── doc ├── Credits.md ├── History.md └── References.md ├── docker ├── DOCKER.md └── scripts │ └── start-node.sh ├── eclipse-java-style.xml ├── flake.lock ├── flake.nix ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── html ├── api-doc │ ├── converter.js │ ├── index.html │ ├── main.css │ ├── rapidoc-min.js │ ├── signum-api.json │ ├── signum_logo.png │ └── version.js └── ui │ ├── assets │ ├── Montserrat-Regular.ttf │ ├── anim.js │ ├── blockchain.jpg │ ├── index.js │ ├── main.css │ ├── normalize.css │ ├── phoenix_v.svg │ ├── signum-logomark-white.svg │ ├── signum-wordmark-white.svg │ └── vars.css │ ├── classic │ └── README.md │ ├── favicon.ico │ ├── index.html │ ├── legacy_api_doc_assets │ ├── bootstrap.min.css │ ├── bootstrap.min.js │ ├── glyphicons-halflings-regular.eot │ ├── glyphicons-halflings-regular.svg │ ├── glyphicons-halflings-regular.ttf │ ├── glyphicons-halflings-regular.woff │ ├── glyphicons-halflings-regular.woff2 │ └── jquery.min.js │ └── phoenix │ └── README.md ├── neo-page ├── .eslintrc.cjs ├── .gitignore ├── .nvmrc ├── README.md ├── index.html ├── package-lock.json ├── package.json ├── public │ ├── 3d │ │ └── earth.gltf │ ├── favicon.ico │ ├── images │ │ ├── alias.webp │ │ ├── api-icon.webp │ │ ├── bg.webp │ │ ├── cashback-cta.webp │ │ ├── cashback.webp │ │ ├── developers-ballmer-min.gif │ │ ├── extension.webp │ │ ├── mobile.webp │ │ ├── neo-wallet.webp │ │ ├── phoenix.webp │ │ ├── signum-neon-logo.webp │ │ ├── signum-symbol.webp │ │ ├── signum-translucid.webp │ │ └── woman-holding-hdd.webp │ └── sounds │ │ ├── click.mp3 │ │ └── intro.mp3 ├── src │ ├── App.tsx │ ├── components │ │ ├── HeightChip │ │ │ ├── HeightChip.css.ts │ │ │ ├── HeightChip.tsx │ │ │ └── index.ts │ │ ├── Layout │ │ │ ├── components │ │ │ │ ├── Alerts │ │ │ │ │ ├── Alerts.css.ts │ │ │ │ │ ├── Alerts.tsx │ │ │ │ │ └── index.ts │ │ │ │ ├── Background │ │ │ │ │ ├── Background.css.ts │ │ │ │ │ ├── Background.tsx │ │ │ │ │ └── index.ts │ │ │ │ ├── Footer │ │ │ │ │ ├── Footer.tsx │ │ │ │ │ └── index.ts │ │ │ │ ├── Header │ │ │ │ │ ├── Header.css.ts │ │ │ │ │ ├── Header.tsx │ │ │ │ │ ├── components │ │ │ │ │ │ ├── NavLinks │ │ │ │ │ │ │ ├── NavLinks.css.ts │ │ │ │ │ │ │ ├── NavLinks.tsx │ │ │ │ │ │ │ └── index.ts │ │ │ │ │ │ └── SocialLinks │ │ │ │ │ │ │ ├── SocialLinks.css.ts │ │ │ │ │ │ │ ├── SocialLinks.tsx │ │ │ │ │ │ │ └── index.ts │ │ │ │ │ └── index.ts │ │ │ │ └── SyncAlert │ │ │ │ │ ├── SyncAlert.css.ts │ │ │ │ │ ├── SyncAlert.tsx │ │ │ │ │ └── index.ts │ │ │ └── index.tsx │ │ ├── NeoChip │ │ │ ├── NeoChip.css.ts │ │ │ ├── NeoChip.tsx │ │ │ └── index.ts │ │ ├── ShortcutCard │ │ │ ├── ShortcutCard.css.ts │ │ │ ├── ShortcutCard.tsx │ │ │ └── index.ts │ │ └── SyncChip │ │ │ ├── SyncChip.css.ts │ │ │ ├── SyncChip.tsx │ │ │ └── index.ts │ ├── hooks │ │ ├── useBlockchainStatus.ts │ │ ├── useFetchingInterval.ts │ │ ├── useNodeConstants.ts │ │ ├── useNodeState.ts │ │ ├── useSound.ts │ │ └── useThirdPartyApps.ts │ ├── main.tsx │ ├── pages │ │ ├── apps │ │ │ ├── index.tsx │ │ │ └── sections │ │ │ │ ├── MainApps │ │ │ │ ├── MainApps.css.ts │ │ │ │ ├── MainApps.tsx │ │ │ │ ├── components │ │ │ │ │ └── AppCard │ │ │ │ │ │ ├── AppCard.css.ts │ │ │ │ │ │ ├── AppCard.tsx │ │ │ │ │ │ └── index.ts │ │ │ │ └── index.ts │ │ │ │ └── ThirdPartyApps │ │ │ │ ├── ThirdPartyApps.tsx │ │ │ │ ├── ThirpartyApps.css.ts │ │ │ │ ├── components │ │ │ │ ├── LoadingIndicator │ │ │ │ │ ├── LoadingIndicator.tsx │ │ │ │ │ └── index.ts │ │ │ │ ├── ThirdPartyAppCard │ │ │ │ │ ├── AppCard.css.ts │ │ │ │ │ ├── AppCard.tsx │ │ │ │ │ └── index.ts │ │ │ │ └── ViewSourceButton │ │ │ │ │ ├── ViewSourceButton.css.ts │ │ │ │ │ ├── ViewSourceButton.tsx │ │ │ │ │ └── index.ts │ │ │ │ └── index.ts │ │ ├── docs │ │ │ ├── index.tsx │ │ │ └── sections │ │ │ │ ├── CommunityCta │ │ │ │ ├── CommunityCta.css.ts │ │ │ │ ├── CommunityCta.tsx │ │ │ │ └── index.ts │ │ │ │ ├── Developer │ │ │ │ ├── Developer.tsx │ │ │ │ └── index.ts │ │ │ │ ├── Title │ │ │ │ ├── Title.tsx │ │ │ │ └── index.ts │ │ │ │ ├── Videotutorials │ │ │ │ ├── Videotutorials.tsx │ │ │ │ ├── components │ │ │ │ │ └── VideoTutorialCard │ │ │ │ │ │ ├── VideoTutorialCard.css.ts │ │ │ │ │ │ ├── VideoTutorialCard.tsx │ │ │ │ │ │ └── index.ts │ │ │ │ └── index.ts │ │ │ │ └── Wikis │ │ │ │ ├── components │ │ │ │ └── WikiCard │ │ │ │ │ ├── WikiCard.css.ts │ │ │ │ │ ├── WikiCard.tsx │ │ │ │ │ └── index.ts │ │ │ │ └── index.tsx │ │ ├── home │ │ │ ├── index.tsx │ │ │ └── sections │ │ │ │ ├── HeroBanner │ │ │ │ ├── HeroBanner.tsx │ │ │ │ ├── components │ │ │ │ │ └── Alert │ │ │ │ │ │ ├── Alert.css.ts │ │ │ │ │ │ ├── Alert.tsx │ │ │ │ │ │ └── index.ts │ │ │ │ └── index.ts │ │ │ │ ├── PathCta │ │ │ │ ├── PathCta.css.ts │ │ │ │ ├── PathCta.tsx │ │ │ │ └── index.ts │ │ │ │ ├── Shortcuts │ │ │ │ ├── Shortcuts.css.ts │ │ │ │ ├── Shortcuts.tsx │ │ │ │ └── index.ts │ │ │ │ └── Welcome │ │ │ │ ├── Welcome.css.ts │ │ │ │ ├── Welcome.tsx │ │ │ │ ├── components │ │ │ │ ├── ActionCard │ │ │ │ │ ├── ActionCard.css.ts │ │ │ │ │ ├── ActionCard.tsx │ │ │ │ │ └── index.ts │ │ │ │ └── Spatial │ │ │ │ │ ├── Spatial.tsx │ │ │ │ │ └── index.ts │ │ │ │ └── index.ts │ │ ├── noMatch │ │ │ └── index.tsx │ │ └── stats │ │ │ ├── index.tsx │ │ │ └── sections │ │ │ └── Stats │ │ │ ├── Stats.css.ts │ │ │ ├── Stats.tsx │ │ │ ├── components │ │ │ └── KpiCard │ │ │ │ ├── KpiCard.css.ts │ │ │ │ ├── KpiCard.tsx │ │ │ │ ├── components │ │ │ │ ├── BurnIndicator │ │ │ │ │ ├── BurnIndicator.css.ts │ │ │ │ │ ├── BurnIndicator.tsx │ │ │ │ │ └── index.ts │ │ │ │ └── LoadingIndicator │ │ │ │ │ ├── LoadingIndicator.tsx │ │ │ │ │ └── index.ts │ │ │ │ └── index.ts │ │ │ └── index.ts │ ├── providers │ │ ├── ThemeProvider.tsx │ │ ├── WalletProvider.tsx │ │ ├── index.tsx │ │ └── types.ts │ ├── states │ │ ├── index.ts │ │ ├── store.ts │ │ └── types.ts │ ├── styles │ │ ├── containers.css.ts │ │ ├── global.css.ts │ │ └── theme.ts │ ├── types │ │ ├── BleepsNames.ts │ │ ├── defaultCashBackId.ts │ │ ├── defaultMaxWidth.ts │ │ ├── fetchingIntervals.ts │ │ ├── index.ts │ │ ├── node.ts │ │ ├── socialLinks.ts │ │ ├── thirdPartyApp.ts │ │ └── times.ts │ ├── utils │ │ └── formatNumber.ts │ └── vite-env.d.ts ├── tsconfig.json ├── tsconfig.node.json └── vite.config.ts ├── nix-deps.json ├── openapi ├── .gitignore ├── README.md ├── dist │ └── signum-api.json ├── openapitools.json ├── package-lock.json ├── package.json ├── parameters │ ├── account │ │ └── account.json │ ├── alias │ │ ├── alias.json │ │ └── tld.json │ ├── apiKey.json │ ├── contract │ │ ├── at.json │ │ └── includeDetails.json │ ├── description.json │ ├── firstIndex.json │ ├── lastIndex.json │ ├── timestamp.json │ ├── token │ │ ├── asset.json │ │ ├── heightEnd.json │ │ ├── heightStart.json │ │ ├── order.json │ │ ├── priceNQT.json │ │ ├── quantityQNT.json │ │ └── skipZeroVolume.json │ └── transaction │ │ ├── amountNQT.json │ │ ├── broadcast.json │ │ ├── deadline.json │ │ ├── encryptToSelfMessageData.json │ │ ├── encryptToSelfMessageNonce.json │ │ ├── encryptedMessageData.json │ │ ├── encryptedMessageNonce.json │ │ ├── feeNQT.json │ │ ├── message.json │ │ ├── messageIsText.json │ │ ├── messageToEncrypt.json │ │ ├── messageToEncryptIsText.json │ │ ├── messageToEncryptToSelf.json │ │ ├── messageToEncryptToSelfIsText.json │ │ ├── publicKey.json │ │ ├── recipient.json │ │ ├── recipientPublicKey.json │ │ ├── referencedTransactionFullHash.json │ │ └── secretPhrase.json ├── paths │ ├── addCommitment.json │ ├── admin │ │ ├── backupDB.json │ │ ├── clearUnconfirmedTransactions.json │ │ ├── fullReset.json │ │ └── popOff.json │ ├── alias │ │ ├── buyAlias.json │ │ ├── sellAlias.json │ │ ├── setAlias.json │ │ └── setTLD.json │ ├── broadcastTransaction.json │ ├── contract │ │ └── createATProgram.json │ ├── getters │ │ ├── getAT.json │ │ ├── getATDetails.json │ │ ├── getATIds.json │ │ ├── getATMapValue.json │ │ ├── getATMapValues.json │ │ ├── getATs.json │ │ ├── getAccount.json │ │ ├── getAccountATs.json │ │ ├── getAccountAssets.json │ │ ├── getAccountBlockIds.json │ │ ├── getAccountBlocks.json │ │ ├── getAccountCurrentAskOrders.json │ │ ├── getAccountCurrentBidOrders.json │ │ ├── getAccountId.json │ │ ├── getAccountPublicKey.json │ │ ├── getAccountSubscriptions.json │ │ ├── getAccountTransactionIds.json │ │ ├── getAccountTransactions.json │ │ ├── getAccountsTradeJournal.json │ │ ├── getAccountsWithName.json │ │ ├── getAccountsWithRewardRecipient.json │ │ ├── getAlias.json │ │ ├── getAliases.json │ │ ├── getAliasesByName.json │ │ ├── getAliasesOnSale.json │ │ ├── getAllAssets.json │ │ ├── getAllOpenAskOrders.json │ │ ├── getAllOpenBidOrders.json │ │ ├── getAllTrades.json │ │ ├── getAskOrder.json │ │ ├── getAskOrders.json │ │ ├── getAsset.json │ │ ├── getAssetAccounts.json │ │ ├── getAssetIds.json │ │ ├── getAssetTransfers.json │ │ ├── getAssetsByIssuer.json │ │ ├── getAssetsByName.json │ │ ├── getAssetsByOwner.json │ │ ├── getBalance.json │ │ ├── getBidOrder.json │ │ ├── getBidOrders.json │ │ ├── getBlock.json │ │ ├── getBlockId.json │ │ ├── getBlockchainStatus.json │ │ ├── getBlocks.json │ │ ├── getConstants.json │ │ ├── getECBlock.json │ │ ├── getIndirectIncoming.json │ │ ├── getMiningInfo.json │ │ ├── getMyInfo.json │ │ ├── getPeer.json │ │ ├── getPeers.json │ │ ├── getRewardRecipient.json │ │ ├── getState.json │ │ ├── getSubscription.json │ │ ├── getSubscriptionPayments.json │ │ ├── getSubscriptionsToAccount.json │ │ ├── getTLDs.json │ │ ├── getTime.json │ │ ├── getTrades.json │ │ ├── getTransaction.json │ │ ├── getUnconfirmedTransactionIds.json │ │ ├── getUnconfirmedTransactions.json │ │ └── suggestFee.json │ ├── parseTransaction.json │ ├── removeCommitment.json │ ├── sendMessage.json │ ├── sendMoney.json │ ├── sendMoneyMulti.json │ ├── sendMoneyMultiSame.json │ ├── sendMoneySubscription.json │ ├── setAccountInfo.json │ ├── setRewardRecipient.json │ ├── signTransaction.json │ ├── submitNonce.json │ ├── subscriptionCancel.json │ └── token │ │ ├── addAssetTreasuryAccount.json │ │ ├── cancelAskOrder.json │ │ ├── cancelBidOrder.json │ │ ├── distributeToAssetHolders.json │ │ ├── issueAsset.json │ │ ├── mintAsset.json │ │ ├── placeAskOrder.json │ │ ├── placeBidOrder.json │ │ ├── transferAsset.json │ │ ├── transferAssetMulti.json │ │ └── transferAssetOwnership.json ├── responses │ ├── constants.json │ ├── empty.json │ ├── error.json │ ├── transaction.json │ └── transactionList.json ├── schemas │ ├── account.json │ ├── address.json │ ├── alias.json │ ├── aliasId.json │ ├── amount.json │ ├── asset.json │ ├── assetDetail.json │ ├── assetId.json │ ├── assetName.json │ ├── block.json │ ├── blockId.json │ ├── contract.json │ ├── contractAddress.json │ ├── contractData.json │ ├── contractId.json │ ├── ecblock.json │ ├── hash.json │ ├── hexString.json │ ├── nextIndex.json │ ├── numericId.json │ ├── order.json │ ├── orderId.json │ ├── orderPricePerQuantity.json │ ├── quantity.json │ ├── rsAddress.json │ ├── signedTransaction.json │ ├── subscription.json │ ├── timestamp.json │ ├── trade.json │ ├── tradeJournal.json │ ├── transaction.json │ ├── transactionId.json │ └── unsignedTransaction.json └── signum-api.json ├── package.nix ├── resources ├── db │ ├── migration_h2_v2 │ │ ├── V10_1__initial_transaction_block_id_index.sql │ │ ├── V10_2__alias_index.sql │ │ ├── V10_3__subscription_index.sql │ │ ├── V10_4__at_index.sql │ │ ├── V11__tx_index_sender_recipient.sql │ │ ├── V1__initial_model.sql │ │ ├── V7_2__account_balance.sql │ │ └── V7_4__account_clean.sql │ ├── migration_mariadb │ │ ├── V10_1__initial_transaction_block_id_index.sql │ │ ├── V10_2__alias_index.sql │ │ ├── V10_3__subscription_index.sql │ │ ├── V10_4__at_index.sql │ │ ├── V10__indices.sql │ │ ├── V11__tx_index_sender_recipient.sql │ │ ├── V12__account_balance_index.sql │ │ ├── V1__initial.sql │ │ ├── V2__indirect_incoming.sql │ │ ├── V3__indirect_incoming_index.sql │ │ ├── V4__subscription_index.sql │ │ ├── V5_2__at_ap_code.sql │ │ ├── V5__at_code_hash.sql │ │ ├── V6_1__indirect_upgrade.sql │ │ ├── V6_2__tx_indices.sql │ │ ├── V6_3__subscription_latest_index.sql │ │ ├── V6__asset_upgrade.sql │ │ ├── V7_1__smart_ats.sql │ │ ├── V7_2__account_balance.sql │ │ ├── V7_4__account_clean.sql │ │ ├── V7_5__index_fix.sql │ │ ├── V7_6__balance_index.sql │ │ ├── V7_7__index_clean.sql │ │ ├── V7_8__add_indices.sql │ │ ├── V7_9__rollback_indices.sql │ │ ├── V7__cashback_and_burn.sql │ │ ├── V8_1__generator_index.sql │ │ ├── V8_2__at_state_index.sql │ │ ├── V8__alias_tld.sql │ │ └── V9__ats_mediumblob.sql │ ├── migration_postgres │ │ ├── V11__tx_index_sender_recipient.sql │ │ ├── V12__account_balance_index.sql │ │ └── V1__initial_model.sql │ └── migration_sqlite │ │ ├── V11__tx_index_sender_recipient.sql │ │ ├── V12__account_balance_index.sql │ │ └── V1__initial_model.sql └── images │ ├── signum_overlay_logo.ico │ ├── signum_overlay_logo.png │ └── signum_testnet_logo.png ├── settings.gradle ├── src ├── brs │ ├── Account.java │ ├── Alias.java │ ├── Appendix.java │ ├── Asset.java │ ├── AssetTransfer.java │ ├── Attachment.java │ ├── Block.java │ ├── Blockchain.java │ ├── BlockchainImpl.java │ ├── BlockchainProcessor.java │ ├── BlockchainProcessorImpl.java │ ├── Constants.java │ ├── DebugTrace.java │ ├── DigitalGoodsStore.java │ ├── EconomicClustering.java │ ├── Escrow.java │ ├── Generator.java │ ├── GeneratorImpl.java │ ├── Genesis.java │ ├── IndirectIncoming.java │ ├── OCLPoC.java │ ├── Order.java │ ├── Signum.java │ ├── SignumException.java │ ├── SignumGUI.java │ ├── Subscription.java │ ├── Token.java │ ├── Trade.java │ ├── Transaction.java │ ├── TransactionProcessor.java │ ├── TransactionProcessorImpl.java │ ├── TransactionType.java │ ├── VerifyTrace.java │ ├── Version.java │ ├── assetexchange │ │ ├── AssetAccountServiceImpl.java │ │ ├── AssetExchange.java │ │ ├── AssetExchangeImpl.java │ │ ├── AssetServiceImpl.java │ │ ├── AssetTransferServiceImpl.java │ │ ├── OrderServiceImpl.java │ │ └── TradeServiceImpl.java │ ├── at │ │ ├── AT.java │ │ ├── ATProcessorCache.java │ │ ├── AtApi.java │ │ ├── AtApiController.java │ │ ├── AtApiHelper.java │ │ ├── AtApiImpl.java │ │ ├── AtApiPlatformImpl.java │ │ ├── AtBlock.java │ │ ├── AtConstants.java │ │ ├── AtController.java │ │ ├── AtError.java │ │ ├── AtException.java │ │ ├── AtMachineProcessor.java │ │ ├── AtMachineState.java │ │ ├── AtTransaction.java │ │ └── OpCode.java │ ├── crypto │ │ ├── Crypto.java │ │ └── EncryptedData.java │ ├── db │ │ ├── BlockDb.java │ │ ├── DerivedTable.java │ │ ├── EntityTable.java │ │ ├── PeerDb.java │ │ ├── SignumKey.java │ │ ├── Table.java │ │ ├── TransactionDb.java │ │ ├── ValuesTable.java │ │ ├── VersionedBatchEntityTable.java │ │ ├── VersionedEntityTable.java │ │ ├── VersionedValuesTable.java │ │ ├── cache │ │ │ ├── DBCacheManagerImpl.java │ │ │ ├── StatisticsCache.java │ │ │ └── TransactionExpiry.java │ │ ├── sql │ │ │ ├── Db.java │ │ │ ├── DbKey.java │ │ │ ├── DbUtils.java │ │ │ ├── DerivedSqlTable.java │ │ │ ├── EntitySqlTable.java │ │ │ ├── SqlATStore.java │ │ │ ├── SqlAccountStore.java │ │ │ ├── SqlAliasStore.java │ │ │ ├── SqlAssetStore.java │ │ │ ├── SqlAssetTransferStore.java │ │ │ ├── SqlBlockDb.java │ │ │ ├── SqlBlockchainStore.java │ │ │ ├── SqlDbs.java │ │ │ ├── SqlDigitalGoodsStoreStore.java │ │ │ ├── SqlEscrowStore.java │ │ │ ├── SqlIndirectIncomingStore.java │ │ │ ├── SqlOrderStore.java │ │ │ ├── SqlPeerDb.java │ │ │ ├── SqlSubscriptionStore.java │ │ │ ├── SqlTradeStore.java │ │ │ ├── SqlTransactionDb.java │ │ │ ├── ValuesSqlTable.java │ │ │ ├── VersionedBatchEntitySqlTable.java │ │ │ ├── VersionedEntitySqlTable.java │ │ │ ├── VersionedValuesSqlTable.java │ │ │ ├── dialects │ │ │ │ ├── DatabaseInstance.java │ │ │ │ ├── DatabaseInstanceBaseImpl.java │ │ │ │ ├── DatabaseInstanceFactory.java │ │ │ │ ├── DatabaseInstanceH2.java │ │ │ │ ├── DatabaseInstanceMariaDb.java │ │ │ │ ├── DatabaseInstancePostgres.java │ │ │ │ └── DatabaseInstanceSqlite.java │ │ │ └── migration │ │ │ │ ├── V5_1__GenerateAtHashes.java │ │ │ │ ├── V6_4__FixBurntAmount.java │ │ │ │ └── V7_3__MigrateBalances.java │ │ └── store │ │ │ ├── ATStore.java │ │ │ ├── AccountStore.java │ │ │ ├── AliasStore.java │ │ │ ├── AssetStore.java │ │ │ ├── AssetTransferStore.java │ │ │ ├── BlockchainStore.java │ │ │ ├── Dbs.java │ │ │ ├── DerivedTableManager.java │ │ │ ├── DigitalGoodsStoreStore.java │ │ │ ├── EscrowStore.java │ │ │ ├── IndirectIncomingStore.java │ │ │ ├── OrderStore.java │ │ │ ├── Stores.java │ │ │ ├── SubscriptionStore.java │ │ │ ├── TradeStore.java │ │ │ └── TransactionProcessorStore.java │ ├── deeplink │ │ ├── DeeplinkGenerator.java │ │ └── DeeplinkQRCodeGenerator.java │ ├── feesuggestions │ │ ├── FeeSuggestion.java │ │ ├── FeeSuggestionCalculator.java │ │ └── FeeSuggestionType.java │ ├── fluxcapacitor │ │ ├── FluxCapacitor.java │ │ ├── FluxCapacitorImpl.java │ │ ├── FluxEnable.java │ │ ├── FluxValue.java │ │ ├── FluxValues.java │ │ └── HistoricalMoments.java │ ├── peer │ │ ├── AddPeers.java │ │ ├── GetBlocksFromHeight.java │ │ ├── GetCumulativeDifficulty.java │ │ ├── GetInfo.java │ │ ├── GetMilestoneBlockIds.java │ │ ├── GetNextBlockIds.java │ │ ├── GetNextBlocks.java │ │ ├── GetPeers.java │ │ ├── GetUnconfirmedTransactions.java │ │ ├── Peer.java │ │ ├── PeerImpl.java │ │ ├── PeerServlet.java │ │ ├── Peers.java │ │ ├── ProcessBlock.java │ │ └── ProcessTransactions.java │ ├── props │ │ ├── CaselessProperties.java │ │ ├── Prop.java │ │ ├── PropertyService.java │ │ ├── PropertyServiceImpl.java │ │ └── Props.java │ ├── schema │ │ ├── Db.java │ │ ├── DefaultCatalog.java │ │ ├── Indexes.java │ │ ├── Keys.java │ │ ├── Tables.java │ │ └── tables │ │ │ ├── Account.java │ │ │ ├── AccountAsset.java │ │ │ ├── AccountBalance.java │ │ │ ├── Alias.java │ │ │ ├── AliasOffer.java │ │ │ ├── AskOrder.java │ │ │ ├── Asset.java │ │ │ ├── AssetTransfer.java │ │ │ ├── At.java │ │ │ ├── AtMap.java │ │ │ ├── AtState.java │ │ │ ├── BidOrder.java │ │ │ ├── Block.java │ │ │ ├── Escrow.java │ │ │ ├── EscrowDecision.java │ │ │ ├── FlywaySchemaHistory.java │ │ │ ├── Goods.java │ │ │ ├── IndirectIncoming.java │ │ │ ├── Peer.java │ │ │ ├── Purchase.java │ │ │ ├── PurchaseFeedback.java │ │ │ ├── PurchasePublicFeedback.java │ │ │ ├── RewardRecipAssign.java │ │ │ ├── Subscription.java │ │ │ ├── Trade.java │ │ │ ├── Transaction.java │ │ │ ├── UnconfirmedTransaction.java │ │ │ └── records │ │ │ ├── AccountAssetRecord.java │ │ │ ├── AccountBalanceRecord.java │ │ │ ├── AccountRecord.java │ │ │ ├── AliasOfferRecord.java │ │ │ ├── AliasRecord.java │ │ │ ├── AskOrderRecord.java │ │ │ ├── AssetRecord.java │ │ │ ├── AssetTransferRecord.java │ │ │ ├── AtMapRecord.java │ │ │ ├── AtRecord.java │ │ │ ├── AtStateRecord.java │ │ │ ├── BidOrderRecord.java │ │ │ ├── BlockRecord.java │ │ │ ├── EscrowDecisionRecord.java │ │ │ ├── EscrowRecord.java │ │ │ ├── FlywaySchemaHistoryRecord.java │ │ │ ├── GoodsRecord.java │ │ │ ├── IndirectIncomingRecord.java │ │ │ ├── PeerRecord.java │ │ │ ├── PurchaseFeedbackRecord.java │ │ │ ├── PurchasePublicFeedbackRecord.java │ │ │ ├── PurchaseRecord.java │ │ │ ├── RewardRecipAssignRecord.java │ │ │ ├── SubscriptionRecord.java │ │ │ ├── TradeRecord.java │ │ │ ├── TransactionRecord.java │ │ │ └── UnconfirmedTransactionRecord.java │ ├── services │ │ ├── ATService.java │ │ ├── AccountService.java │ │ ├── AliasService.java │ │ ├── BlockService.java │ │ ├── DGSGoodsStoreService.java │ │ ├── EscrowService.java │ │ ├── IndirectIncomingService.java │ │ ├── ParameterService.java │ │ ├── SubscriptionService.java │ │ ├── TimeService.java │ │ ├── TransactionService.java │ │ └── impl │ │ │ ├── ATServiceImpl.java │ │ │ ├── AccountServiceImpl.java │ │ │ ├── AliasServiceImpl.java │ │ │ ├── BlockServiceImpl.java │ │ │ ├── DGSGoodsStoreServiceImpl.java │ │ │ ├── EscrowServiceImpl.java │ │ │ ├── IndirectIncomingServiceImpl.java │ │ │ ├── ParameterServiceImpl.java │ │ │ ├── SubscriptionServiceImpl.java │ │ │ ├── TimeServiceImpl.java │ │ │ └── TransactionServiceImpl.java │ ├── statistics │ │ └── StatisticsManagerImpl.java │ ├── transactionduplicates │ │ ├── TransactionDuplicatesCheckerImpl.java │ │ ├── TransactionDuplicationKey.java │ │ └── TransactionDuplicationResult.java │ ├── unconfirmedtransactions │ │ ├── ReservedBalanceCache.java │ │ ├── UnconfirmedTransactionStore.java │ │ ├── UnconfirmedTransactionStoreImpl.java │ │ └── UnconfirmedTransactionTiming.java │ ├── util │ │ ├── BriefLogFormatter.java │ │ ├── CollectionWithIndex.java │ │ ├── Convert.java │ │ ├── CountingInputStream.java │ │ ├── CountingOutputStream.java │ │ ├── DownloadCacheImpl.java │ │ ├── FilteringIterator.java │ │ ├── JSON.java │ │ ├── Listener.java │ │ ├── Listeners.java │ │ ├── LoggerConfigurator.java │ │ ├── MiningPlot.java │ │ ├── Observable.java │ │ ├── SignumLogManager.java │ │ ├── StampedLockUtils.java │ │ ├── StringUtils.java │ │ ├── Subnet.java │ │ ├── TextUtils.java │ │ ├── ThreadPool.java │ │ └── Time.java │ └── web │ │ ├── api │ │ ├── http │ │ │ ├── ApiServlet.java │ │ │ ├── LegacyDocsServlet.java │ │ │ ├── common │ │ │ │ ├── APITransactionManager.java │ │ │ │ ├── APITransactionManagerImpl.java │ │ │ │ ├── JSONData.java │ │ │ │ ├── JSONResponses.java │ │ │ │ ├── LegacyDocTag.java │ │ │ │ ├── ParameterException.java │ │ │ │ ├── ParameterParser.java │ │ │ │ ├── Parameters.java │ │ │ │ └── ResultFields.java │ │ │ └── handler │ │ │ │ ├── AbstractAssetsRetrieval.java │ │ │ │ ├── AbstractGetUnconfirmedTransactions.java │ │ │ │ ├── AddAssetTreasuryAccount.java │ │ │ │ ├── AddCommitment.java │ │ │ │ ├── BackupDB.java │ │ │ │ ├── BroadcastTransaction.java │ │ │ │ ├── BuyAlias.java │ │ │ │ ├── CalculateFullHash.java │ │ │ │ ├── CancelAskOrder.java │ │ │ │ ├── CancelBidOrder.java │ │ │ │ ├── ClearUnconfirmedTransactions.java │ │ │ │ ├── CreateATProgram.java │ │ │ │ ├── CreateTransaction.java │ │ │ │ ├── DGSDelisting.java │ │ │ │ ├── DGSDelivery.java │ │ │ │ ├── DGSFeedback.java │ │ │ │ ├── DGSListing.java │ │ │ │ ├── DGSPriceChange.java │ │ │ │ ├── DGSPurchase.java │ │ │ │ ├── DGSQuantityChange.java │ │ │ │ ├── DGSRefund.java │ │ │ │ ├── DecryptFrom.java │ │ │ │ ├── DistributeToAssetHolders.java │ │ │ │ ├── EncryptTo.java │ │ │ │ ├── EscrowSign.java │ │ │ │ ├── FullReset.java │ │ │ │ ├── GenerateDeeplink.java │ │ │ │ ├── GenerateDeeplinkQR.java │ │ │ │ ├── GenerateDeeplinkQRCode.java │ │ │ │ ├── GenerateToken.java │ │ │ │ ├── GetAT.java │ │ │ │ ├── GetATDetails.java │ │ │ │ ├── GetATIds.java │ │ │ │ ├── GetATLong.java │ │ │ │ ├── GetATMapValue.java │ │ │ │ ├── GetATMapValues.java │ │ │ │ ├── GetATs.java │ │ │ │ ├── GetAccount.java │ │ │ │ ├── GetAccountATs.java │ │ │ │ ├── GetAccountAssets.java │ │ │ │ ├── GetAccountBlockIds.java │ │ │ │ ├── GetAccountBlocks.java │ │ │ │ ├── GetAccountCurrentAskOrderIds.java │ │ │ │ ├── GetAccountCurrentAskOrders.java │ │ │ │ ├── GetAccountCurrentBidOrderIds.java │ │ │ │ ├── GetAccountCurrentBidOrders.java │ │ │ │ ├── GetAccountEscrowTransactions.java │ │ │ │ ├── GetAccountId.java │ │ │ │ ├── GetAccountPublicKey.java │ │ │ │ ├── GetAccountSubscriptions.java │ │ │ │ ├── GetAccountTransactionIds.java │ │ │ │ ├── GetAccountTransactions.java │ │ │ │ ├── GetAccountsWithName.java │ │ │ │ ├── GetAccountsWithRewardRecipient.java │ │ │ │ ├── GetAlias.java │ │ │ │ ├── GetAliases.java │ │ │ │ ├── GetAliasesByName.java │ │ │ │ ├── GetAliasesOnSale.java │ │ │ │ ├── GetAllAssets.java │ │ │ │ ├── GetAllOpenAskOrders.java │ │ │ │ ├── GetAllOpenBidOrders.java │ │ │ │ ├── GetAllTrades.java │ │ │ │ ├── GetAskOrder.java │ │ │ │ ├── GetAskOrderIds.java │ │ │ │ ├── GetAskOrders.java │ │ │ │ ├── GetAsset.java │ │ │ │ ├── GetAssetAccounts.java │ │ │ │ ├── GetAssetIds.java │ │ │ │ ├── GetAssetTransfers.java │ │ │ │ ├── GetAssetsByIssuer.java │ │ │ │ ├── GetAssetsByName.java │ │ │ │ ├── GetAssetsByOwner.java │ │ │ │ ├── GetBalance.java │ │ │ │ ├── GetBidOrder.java │ │ │ │ ├── GetBidOrderIds.java │ │ │ │ ├── GetBidOrders.java │ │ │ │ ├── GetBlock.java │ │ │ │ ├── GetBlockId.java │ │ │ │ ├── GetBlockchainStatus.java │ │ │ │ ├── GetBlocks.java │ │ │ │ ├── GetConstants.java │ │ │ │ ├── GetDGSGood.java │ │ │ │ ├── GetDGSGoods.java │ │ │ │ ├── GetDGSPendingPurchases.java │ │ │ │ ├── GetDGSPurchase.java │ │ │ │ ├── GetDGSPurchases.java │ │ │ │ ├── GetECBlock.java │ │ │ │ ├── GetEscrowTransaction.java │ │ │ │ ├── GetIndirectIncoming.java │ │ │ │ ├── GetMiningInfo.java │ │ │ │ ├── GetMyInfo.java │ │ │ │ ├── GetMyPeerInfo.java │ │ │ │ ├── GetPeer.java │ │ │ │ ├── GetPeers.java │ │ │ │ ├── GetRewardRecipient.java │ │ │ │ ├── GetState.java │ │ │ │ ├── GetSubscription.java │ │ │ │ ├── GetSubscriptionPayments.java │ │ │ │ ├── GetSubscriptionsToAccount.java │ │ │ │ ├── GetTLDs.java │ │ │ │ ├── GetTime.java │ │ │ │ ├── GetTradeJournal.java │ │ │ │ ├── GetTrades.java │ │ │ │ ├── GetTransaction.java │ │ │ │ ├── GetTransactionBytes.java │ │ │ │ ├── GetTransactionIds.java │ │ │ │ ├── GetUnconfirmedTransactionIds.java │ │ │ │ ├── GetUnconfirmedTransactions.java │ │ │ │ ├── IssueAsset.java │ │ │ │ ├── LongConvert.java │ │ │ │ ├── MintAsset.java │ │ │ │ ├── ParseTransaction.java │ │ │ │ ├── PlaceAskOrder.java │ │ │ │ ├── PlaceBidOrder.java │ │ │ │ ├── PopOff.java │ │ │ │ ├── RSConvert.java │ │ │ │ ├── ReadMessage.java │ │ │ │ ├── RemoveCommitment.java │ │ │ │ ├── SellAlias.java │ │ │ │ ├── SendMessage.java │ │ │ │ ├── SendMoney.java │ │ │ │ ├── SendMoneyEscrow.java │ │ │ │ ├── SendMoneyMulti.java │ │ │ │ ├── SendMoneyMultiSame.java │ │ │ │ ├── SendMoneySubscription.java │ │ │ │ ├── SetAccountInfo.java │ │ │ │ ├── SetAlias.java │ │ │ │ ├── SetRewardRecipient.java │ │ │ │ ├── SetTLD.java │ │ │ │ ├── SignTransaction.java │ │ │ │ ├── SubmitNonce.java │ │ │ │ ├── SubscriptionCancel.java │ │ │ │ ├── SuggestFee.java │ │ │ │ ├── TransferAsset.java │ │ │ │ ├── TransferAssetMulti.java │ │ │ │ └── TransferAssetOwnership.java │ │ └── ws │ │ │ ├── BlockchainEventNotifier.java │ │ │ ├── WebSocketConnection.java │ │ │ ├── WebSocketConnectionAdapter.java │ │ │ ├── WebSocketConnectionCreator.java │ │ │ ├── common │ │ │ ├── BaseWebSocketResponse.java │ │ │ ├── Debouncer.java │ │ │ ├── JSONWebSocketResponse.java │ │ │ ├── SimpleScheduler.java │ │ │ └── WebsocketEventNames.java │ │ │ └── emitter │ │ │ ├── AbstractWebSocketEventEmitterImpl.java │ │ │ ├── BlockPushedEventEmitter.java │ │ │ ├── ConnectedEventEmitter.java │ │ │ ├── HeartBeatEventEmitter.java │ │ │ ├── PendingTransactionsAddedEventEmitter.java │ │ │ ├── WebSocketEventEmitter.java │ │ │ └── data │ │ │ └── ConnectedEventData.java │ │ └── server │ │ ├── AbstractServerConnectorBuilder.java │ │ ├── ServerConnectorBuilder.java │ │ ├── ServerConnectorFactory.java │ │ ├── ServerConnectorHttpBuilderImpl.java │ │ ├── ServerConnectorWebsocketBuilderImpl.java │ │ ├── WebServer.java │ │ ├── WebServerContext.java │ │ └── WebServerImpl.java └── signum │ ├── Launcher.java │ └── net │ ├── MockNetwork.java │ ├── NetworkParameters.java │ ├── NetworkParametersBase.java │ ├── TestnetNetwork.java │ └── TestnetNetwork2.java ├── test ├── java │ ├── brs │ │ ├── GeneratorImplTest.java │ │ ├── MockGeneratorTest.java │ │ ├── assetexchange │ │ │ ├── AssetAccountServiceImplTest.java │ │ │ ├── AssetServiceImplTest.java │ │ │ ├── AssetTransferServiceImplTest.java │ │ │ ├── OrderServiceImplTest.java │ │ │ └── TradeServiceImplTest.java │ │ ├── at │ │ │ ├── ATTest.java │ │ │ ├── AtApiHelperTest.java │ │ │ ├── AtControllerTest.java │ │ │ └── AtTestHelper.java │ │ ├── common │ │ │ ├── AbstractUnitTest.java │ │ │ ├── JSONTestHelper.java │ │ │ ├── QuickMocker.java │ │ │ ├── TestConstants.java │ │ │ └── TestInfrastructure.java │ │ ├── crypto │ │ │ └── CryptoTest.java │ │ ├── deeplink │ │ │ ├── DeeplinkGeneratorTest.java │ │ │ └── DeeplinkQRCodeGeneratorTest.java │ │ ├── entity │ │ │ └── VersionTest.java │ │ ├── feesuggestions │ │ │ └── FeeSuggestionCalculatorTest.java │ │ ├── fluxcapacitor │ │ │ └── FluxCapacitorImplTest.java │ │ ├── peer │ │ │ ├── GetCumulativeDifficultyTest.java │ │ │ ├── GetNextBlockIdsTest.java │ │ │ └── GetNextBlocksTest.java │ │ ├── services │ │ │ └── impl │ │ │ │ ├── ATServiceImplTest.java │ │ │ │ ├── AccountServiceImplTest.java │ │ │ │ ├── AliasServiceImplTest.java │ │ │ │ ├── DGSGoodsStoreServiceImplTest.java │ │ │ │ ├── EscrowServiceImplTest.java │ │ │ │ ├── ExpiredPurchaseListenerTest.java │ │ │ │ ├── IndirectIncomingServiceImplTest.java │ │ │ │ ├── ParameterServiceImplTest.java │ │ │ │ └── SubscriptionServiceImplTest.java │ │ ├── transactionduplicates │ │ │ └── TransactionDuplicatesCheckerImplTest.java │ │ ├── unconfirmedtransactions │ │ │ └── UnconfirmedTransactionStoreTest.java │ │ ├── util │ │ │ └── TextUtilsTest.java │ │ └── web │ │ │ └── api │ │ │ └── http │ │ │ └── handler │ │ │ ├── AbstractTransactionTest.java │ │ │ ├── BroadcastTransactionTest.java │ │ │ ├── BuyAliasTest.java │ │ │ ├── CalculateFullHashTest.java │ │ │ ├── CancelAskOrderTest.java │ │ │ ├── CancelBidOrderTest.java │ │ │ ├── ClearUnconfirmedTransactionsTest.java │ │ │ ├── CreateATProgramTest.java │ │ │ ├── DGSDelistingTest.java │ │ │ ├── DGSDeliveryTest.java │ │ │ ├── DGSFeedbackTest.java │ │ │ ├── DGSListingTest.java │ │ │ ├── DGSPriceChangeTest.java │ │ │ ├── DGSPurchaseTest.java │ │ │ ├── DGSQuantityChangeTest.java │ │ │ ├── DGSRefundTest.java │ │ │ ├── DecryptFromTest.java │ │ │ ├── EscrowSignTest.java │ │ │ ├── FullResetTest.java │ │ │ ├── GetAccountATsTest.java │ │ │ ├── GetAccountBlockIdsTest.java │ │ │ ├── GetAccountBlocksTest.java │ │ │ ├── GetAccountCurrentAskOrderIdsTest.java │ │ │ ├── GetAccountCurrentAskOrdersTest.java │ │ │ ├── GetAccountCurrentBidOrderIdsTest.java │ │ │ ├── GetAccountCurrentBidOrdersTest.java │ │ │ ├── GetAccountEscrowTransactionsTest.java │ │ │ ├── GetAccountIdTest.java │ │ │ ├── GetAccountPublicKeyTest.java │ │ │ ├── GetAccountSubscriptionsTest.java │ │ │ ├── GetAccountTest.java │ │ │ ├── GetAccountsWithNameTest.java │ │ │ ├── GetAccountsWithRewardRecipientTest.java │ │ │ ├── GetAliasTest.java │ │ │ ├── GetAliasesTest.java │ │ │ ├── GetAllAssetsTest.java │ │ │ ├── GetAllOpenAskOrdersTest.java │ │ │ ├── GetAllOpenBidOrdersTest.java │ │ │ ├── GetAllTradesTest.java │ │ │ ├── GetAskOrderIdsTest.java │ │ │ ├── GetAskOrderTest.java │ │ │ ├── GetAskOrdersTest.java │ │ │ ├── GetAssetIdsTest.java │ │ │ ├── GetAssetTest.java │ │ │ ├── GetAssetTransfersTest.java │ │ │ ├── GetAssetsByIssuerTest.java │ │ │ ├── GetBalanceTest.java │ │ │ ├── GetBidOrderTest.java │ │ │ ├── GetBidOrdersTest.java │ │ │ ├── GetBlockTest.java │ │ │ ├── GetDGSGoodTest.java │ │ │ ├── GetDGSGoodsTest.java │ │ │ ├── GetDGSPendingPurchasesTest.java │ │ │ ├── GetDGSPurchaseTest.java │ │ │ ├── GetDGSPurchasesTest.java │ │ │ ├── GetRewardRecipientTest.java │ │ │ ├── GetTimeTest.java │ │ │ ├── GetTradesTest.java │ │ │ ├── IssueAssetTest.java │ │ │ ├── ParameterParserTest.java │ │ │ ├── SellAliasTest.java │ │ │ ├── SetAliasTest.java │ │ │ ├── SetRewardRecipientTest.java │ │ │ ├── SubscriptionCancelTest.java │ │ │ ├── SuggestFeeTest.java │ │ │ └── TransferAssetTest.java │ ├── chain │ │ ├── AliasTest.java │ │ ├── AssetTest.java │ │ ├── ChainUtils.java │ │ └── SendTransactionsTest.java │ └── it │ │ ├── common │ │ ├── APISender.java │ │ ├── AbstractIT.java │ │ └── BlockMessageBuilder.java │ │ └── java │ │ └── brs │ │ ├── AlternativeRealityTest.java │ │ └── ProcessASingleBlockTest.java └── resources │ └── alternatereality │ ├── reality1.json │ └── reality2.json ├── update-classic.sh ├── update-openapi.sh └── update-phoenix.sh /.dockerignore: -------------------------------------------------------------------------------- 1 | .github/ 2 | .gradle/ 3 | .idea/ 4 | bin/ 5 | build/ 6 | doc/ 7 | t/ 8 | db/ 9 | target/ 10 | openapi/node_modules/ 11 | temp/ 12 | 13 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | 3 | root = true 4 | 5 | [*] 6 | indent_style = space 7 | indent_size = 2 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | end_of_line = lf 11 | charset = utf-8 12 | 13 | # Use 2 spaces for frontend files 14 | [{*.html,*.js,*css}] 15 | indent_size = 2 16 | 17 | [{*.yml,*.yaml}] 18 | indent_size = 2 19 | 20 | # The JSON files contain newlines inconsistently 21 | [*.json] 22 | insert_final_newline = false 23 | indent_size = 2 24 | 25 | # Minified JavaScript files shouldn't be changed 26 | [**.min.js] 27 | insert_final_newline = false 28 | 29 | # Batch files use tabs for indentation 30 | [*.bat] 31 | indent_style = tab 32 | 33 | [*.md] 34 | trim_trailing_whitespace = false 35 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Set the default behavior, in case people don't have core.autocrlf set. 2 | * text=auto 3 | 4 | # Explicitly declare text files you want to always be normalized and converted 5 | # to native line endings on checkout. 6 | *.java text 7 | *.html text 8 | 9 | # Declare files that will always have specific line endings on checkout. 10 | *.js text eol=lf 11 | *.json text eol=lf 12 | *.sh text eol=lf 13 | *.cmd text eol=crlf 14 | *.bat text eol=crlf 15 | 16 | # Denote all files that are truly binary and should not be modified. 17 | *.png binary 18 | *.jpg binary 19 | *.gif binary 20 | *.ico binary 21 | *.jar binary 22 | *.dll binary 23 | *.so binary 24 | *.dat binary 25 | *.otf binary 26 | *.eot binary 27 | *.svg binary 28 | *.ttf binary 29 | *.woff binary -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @jjos2372 2 | /html/ @ghost 3 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: jjos2372 2 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | # This workflow will build a Java project with Maven 2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven 3 | 4 | name: Build Signum Node 5 | 6 | on: 7 | pull_request: 8 | push: 9 | branches: 10 | - '**' 11 | tags-ignore: 12 | - 'v*' 13 | 14 | jobs: 15 | build: 16 | runs-on: ubuntu-latest 17 | steps: 18 | - uses: actions/checkout@v4 19 | - name: Set up JDK 21 20 | uses: actions/setup-java@v4 21 | with: 22 | distribution: 'zulu' 23 | java-version: '21' 24 | - name: Build with Gradle and run all tests 25 | run: ./gradlew test 26 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /*.iml 2 | /dist 3 | /tmp 4 | /temp 5 | .idea 6 | *.log 7 | /conf/logging.properties 8 | /conf/brs.properties 9 | /conf/node.properties 10 | _config.yml 11 | /html/ui/doc/* 12 | /html/ui/phoenix/* 13 | /html/ui/classic/* 14 | !/html/ui/phoenix/README.md 15 | !/html/ui/classic/README.md 16 | target 17 | *.prefs 18 | .project 19 | .classpath 20 | /burst_db/* 21 | /db/* 22 | /conf-tests/ 23 | *.zip 24 | *.jar 25 | *.hprof 26 | .DS_Store 27 | #ignore everything in here by default, but settings.json is already committed 28 | #and so will remain tracked 29 | **/.vscode 30 | 31 | /.gradle/ 32 | /build/ 33 | /bin/ 34 | launch.json 35 | *.pem 36 | *.p12 37 | *.log.lck 38 | 39 | result 40 | -------------------------------------------------------------------------------- /.jitpack.yml: -------------------------------------------------------------------------------- 1 | jdk: openjdk11 2 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "java.format.settings.url": "./eclipse-java-style.xml", 3 | "java.format.settings.profile": "SignumStyle", 4 | "java.checkstyle.configuration": "${workspaceFolder}/checkstyle.xml", 5 | "java.checkstyle.version": "10.22.0", 6 | "java.format.onType.enabled": true, 7 | "java.format.enabled": true, 8 | "editor.detectIndentation": false, 9 | "java.import.projectSelection": "automatic", 10 | "workbench.colorTheme": "Default Dark Modern", 11 | "java.server.launchMode": "Standard" 12 | } 13 | -------------------------------------------------------------------------------- /ci/updateClassic.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | echo "========================================" 6 | echo "🛰 Updating to latest Classic Version..." 7 | echo "----------------------------------------" 8 | BASE_CI_DIR=$(pwd) 9 | 10 | # prepare tmp folder 11 | TMPDIR=$(mktemp -d) 12 | cd $TMPDIR > /dev/null 13 | 14 | # download 15 | echo 16 | echo "=======================================" 17 | echo "⬇️ Cloning Classic wallet main branch..." 18 | echo "---------------------------------------" 19 | git clone https://github.com/signum-network/signum-classic-wallet.git 20 | cd signum-classic-wallet/src > /dev/null 21 | 22 | # cleanup old version 23 | rm -rf ${BASE_CI_DIR}/../html/ui/classic/* 24 | cp -R * ${BASE_CI_DIR}/../html/ui/classic/ 25 | echo "✅ Copied wallet sources" 26 | 27 | echo 28 | echo "=======================================" 29 | echo "🛀 Cleaning up..." 30 | echo "---------------------------------------" 31 | cd ${BASE_CI_DIR} 32 | rm -rf ${TMPDIR} 33 | echo "✅ Removed temp data" 34 | echo 35 | echo "🎉 Yay. Successfully updated Classic Wallet" 36 | -------------------------------------------------------------------------------- /conf/junit/node-default.properties: -------------------------------------------------------------------------------- 1 | ####################################################################### 2 | # Mock configuration file # 3 | ####################################################################### 4 | 5 | # Mock mining for junit tests, in-memory db (offline and accepting any nonce as valid) 6 | node.network = signum.net.MockNetwork 7 | 8 | #DB.Url=jdbc:h2:mem:signum-mock;DB_CLOSE_ON_EXIT=FALSE 9 | # Database connection JDBC url 10 | DB.Url=jdbc:sqlite:file:./db/signum-mock.sqlite.db 11 | -------------------------------------------------------------------------------- /conf/mainnet/node.h2.properties: -------------------------------------------------------------------------------- 1 | ################################################################################################# 2 | # 3 | # H2 is deprecated....Please stop using H2 (in mainnet) and move to Sqlite for local nodes 4 | # For public nodes go with MariaDB or Postgres 5 | # 6 | # 7 | # This file is kept only for backwards compatibility 8 | # 9 | ################################################################################################# 10 | 11 | 12 | #### API SERVER #### 13 | API.Listen = 0.0.0.0 14 | API.allowed = * 15 | 16 | #### DATABASE #### 17 | # Reduces the database file size dramatically, if on... but needs time on shutdown 18 | # Db.H2. DefragOnShutdown is deprecated and now Db.Optimize 19 | DB.Optimize = on 20 | # Database connection JDBC url 21 | DB.Url=jdbc:h2:file:/db/signum;DB_CLOSE_ON_EXIT=FALSE 22 | DB.Username= 23 | DB.Password= 24 | -------------------------------------------------------------------------------- /conf/mainnet/node.mariadb.properties: -------------------------------------------------------------------------------- 1 | #### API SERVER #### 2 | API.Listen = 0.0.0.0 3 | API.allowed = * 4 | 5 | #### DATABASE #### 6 | 7 | # Database connection JDBC url 8 | # Append ;AUTO_SERVER=TRUE to enable automatic mixed mode access. 9 | DB.Url=jdbc:mariadb://localhost:3306/signum?sslMode=DISABLED 10 | DB.Username=root 11 | DB.Password=signum 12 | -------------------------------------------------------------------------------- /conf/mainnet/node.postgres.properties: -------------------------------------------------------------------------------- 1 | #### API SERVER #### 2 | API.Listen = 0.0.0.0 3 | API.allowed = * 4 | 5 | #### DATABASE #### 6 | 7 | DB.Url=jdbc:postgresql://localhost:5432/signum?sslMode=disabled 8 | DB.Username=signumnode 9 | DB.Password=s1gn00m_n0d3 10 | -------------------------------------------------------------------------------- /conf/mock/node-default.properties: -------------------------------------------------------------------------------- 1 | ####################################################################### 2 | # Mock configuration file # 3 | ####################################################################### 4 | 5 | # Mock mining (offline and accepting any nonce as valid) 6 | node.network = signum.net.MockNetwork 7 | -------------------------------------------------------------------------------- /conf/mock/node.properties: -------------------------------------------------------------------------------- 1 | node.network = signum.net.MockNetwork 2 | DB.SqliteJournalMode = WAL 3 | 4 | # Database connection JDBC url 5 | DB.Url=jdbc:sqlite:file:./db/signum-test.sqlite.db 6 | 7 | SoloMiningPassphrases="some phrase" 8 | AllowOtherSoloMiners=true 9 | -------------------------------------------------------------------------------- /conf/mock/node.sqlite-mock.properties: -------------------------------------------------------------------------------- 1 | DB.SqliteJournalMode = WAL 2 | 3 | # Database connection JDBC url 4 | DB.Url=jdbc:sqlite:file:./db/signum-mock.sqlite.db 5 | -------------------------------------------------------------------------------- /conf/testnet/node.h2.properties: -------------------------------------------------------------------------------- 1 | ################################################################################################# 2 | # 3 | # H2 is deprecated....Please stop using H2 and move to Sqlite for local nodes 4 | # For public nodes go with MariaDB or Postgres 5 | # 6 | # 7 | # This file is kept only for backwards compatibility 8 | # 9 | ################################################################################################# 10 | 11 | node.network = signum.net.TestnetNetwork 12 | 13 | #### API SERVER #### 14 | API.Listen = 0.0.0.0 15 | API.allowed = * 16 | 17 | #### DATABASE #### 18 | # Reduces the database file size dramatically, if on... but needs time on shutdown 19 | Db.H2.DefragOnShutdown = on 20 | # Database connection JDBC url 21 | DB.Url=jdbc:h2:file:/db/signum-test;DB_CLOSE_ON_EXIT=FALSE 22 | DB.Username= 23 | DB.Password= 24 | -------------------------------------------------------------------------------- /conf/testnet/node.mariadb.properties: -------------------------------------------------------------------------------- 1 | node.network = signum.net.TestnetNetwork 2 | 3 | #### API SERVER #### 4 | API.Listen = 0.0.0.0 5 | API.allowed = * 6 | 7 | #### DATABASE #### 8 | 9 | # Database connection JDBC url 10 | # Append ;AUTO_SERVER=TRUE to enable automatic mixed mode access. 11 | DB.Url=jdbc:mariadb://localhost:3306/signum-test?sslMode=DISABLED 12 | DB.Username=root 13 | DB.Password=signum 14 | -------------------------------------------------------------------------------- /conf/testnet/node.postgres.properties: -------------------------------------------------------------------------------- 1 | #### API SERVER #### 2 | API.Listen = 0.0.0.0 3 | API.allowed = * 4 | 5 | #### DATABASE #### 6 | 7 | DB.Url=jdbc:postgresql://localhost:5432/signum-test?sslMode=disabled 8 | DB.Username=signumnode 9 | DB.Password=s1gn00m_n0d3 10 | -------------------------------------------------------------------------------- /conf/testnet/node.sqlite.properties: -------------------------------------------------------------------------------- 1 | #### API SERVER #### 2 | API.Listen = 0.0.0.0 3 | API.allowed = * 4 | 5 | #### DATABASE #### 6 | # Runs VACUUM and OPTIMIZE for SQLite. Reduces file size 7 | DB.Optimize = on 8 | 9 | ## Sqlite Journaling Mode 10 | ## https://www.sqlite.org/pragma.html#pragma_journal_mode 11 | ## Possible Values are: DELETE,TRUNCATE,PERSIST,WAL (default, recommended) 12 | ## WAL may occupy up to twice more disc space than others while running the node, but allows read concurrency and usually better performance (see more here: https://www.sqlite.org/wal.html) 13 | ## It's highly recommended to use WAL mode during syncing, to dramatically reduce I/O operations and though faster sync times. 14 | ## Info: MEMORY journal mode is not supported 15 | DB.SqliteJournalMode = WAL 16 | 17 | # Database connection JDBC url 18 | DB.Url=jdbc:sqlite:file:./db/signum-test.sqlite.db 19 | DB.Username= 20 | DB.Password= 21 | -------------------------------------------------------------------------------- /doc/References.md: -------------------------------------------------------------------------------- 1 | For further information, please visit the following pages. 2 | 3 | Wiki: https://wiki.signum.network/ 4 | 5 | Info: https://signum.network 6 | 7 | Explorer: https://explorer.signum.network/ 8 | 9 | Basic Documentation: https://docs.signum.network/signum 10 | 11 | Ecosystem: https://docs.signum.network/ecosystem 12 | 13 | 14 | ### Additional Software 15 | 16 | BTDEX: https://btdex.trade/ 17 | Phoenix Wallet: https://phoenix-wallet.rocks/ 18 | 19 | ### Games on chain 20 | 21 | Cryptoball: https://www.cryptoball.org/ 22 | 23 | Blockplay: https://blockplay.io/ 24 | 25 | The Mining Game: https://tmg.notallmine.net/ 26 | 27 | TMG Lotto: https://deleterium.info/tmg-lotto/ 28 | 29 | Wheel of Signa: https://wos.notallmine.net/ -------------------------------------------------------------------------------- /flake.lock: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "nixpkgs": { 4 | "locked": { 5 | "lastModified": 1746461020, 6 | "narHash": "sha256-7+pG1I9jvxNlmln4YgnlW4o+w0TZX24k688mibiFDUE=", 7 | "owner": "nixos", 8 | "repo": "nixpkgs", 9 | "rev": "3730d8a308f94996a9ba7c7138ede69c1b9ac4ae", 10 | "type": "github" 11 | }, 12 | "original": { 13 | "owner": "nixos", 14 | "ref": "nixos-unstable", 15 | "repo": "nixpkgs", 16 | "type": "github" 17 | } 18 | }, 19 | "root": { 20 | "inputs": { 21 | "nixpkgs": "nixpkgs" 22 | } 23 | } 24 | }, 25 | "root": "root", 26 | "version": 7 27 | } 28 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/signum-network/signum-node/c064beb03264dcb7f49349dfd2b005511d19e1a2/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip 4 | networkTimeout=10000 5 | validateDistributionUrl=true 6 | zipStoreBase=GRADLE_USER_HOME 7 | zipStorePath=wrapper/dists 8 | -------------------------------------------------------------------------------- /html/api-doc/converter.js: -------------------------------------------------------------------------------- 1 | class Converter { 2 | 3 | _value = 0.0 4 | _decimals = 8 5 | _quantity = 0 6 | 7 | 8 | get value() { 9 | return this._value 10 | } 11 | 12 | get quantity() { 13 | return this._quantity 14 | } 15 | 16 | get decimals() { 17 | return this._decimals 18 | } 19 | 20 | dispatch() { 21 | document.dispatchEvent(new CustomEvent('convert', { 22 | detail: { 23 | quantity: this.quantity, 24 | value: this.value, 25 | decimals: this.decimals, 26 | } 27 | })) 28 | } 29 | 30 | setDecimals(d){ 31 | this._decimals = d 32 | this._quantity = this._value * ( 10 ** this._decimals) 33 | this._value = this._quantity / (10 ** this._decimals) 34 | this.dispatch() 35 | } 36 | 37 | setValue(v){ 38 | this._value = v 39 | this._quantity = this._value * ( 10 ** this._decimals) 40 | this.dispatch() 41 | } 42 | 43 | setQuantity(q){ 44 | this._quantity = q 45 | this._value = this._quantity / (10 ** this._decimals) 46 | this.dispatch() 47 | } 48 | } 49 | 50 | window.converter = new Converter() 51 | -------------------------------------------------------------------------------- /html/api-doc/signum_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/signum-network/signum-node/c064beb03264dcb7f49349dfd2b005511d19e1a2/html/api-doc/signum_logo.png -------------------------------------------------------------------------------- /html/api-doc/version.js: -------------------------------------------------------------------------------- 1 | async function fetchVersion() { 2 | const headers = new Headers({ 3 | 'Accept': 'application/json' 4 | }) 5 | const response = await fetch(`${location.origin}/api?requestType=getBlockchainStatus`, {headers}) 6 | if (response.ok) { 7 | const {version} = await response.json() 8 | return version; 9 | } 10 | return "" 11 | } 12 | -------------------------------------------------------------------------------- /html/ui/assets/Montserrat-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/signum-network/signum-node/c064beb03264dcb7f49349dfd2b005511d19e1a2/html/ui/assets/Montserrat-Regular.ttf -------------------------------------------------------------------------------- /html/ui/assets/blockchain.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/signum-network/signum-node/c064beb03264dcb7f49349dfd2b005511d19e1a2/html/ui/assets/blockchain.jpg -------------------------------------------------------------------------------- /html/ui/assets/index.js: -------------------------------------------------------------------------------- 1 | const nodeUrl = location.origin 2 | const preferredWalletKey = 'preferred-wallet' 3 | 4 | async function getNodeVersion() { 5 | const url = `${nodeUrl}/api?requestType=getBlockchainStatus` 6 | const res = await fetch(url) 7 | 8 | if (!res.ok) { 9 | console.error('Request to peer failed', res.status) 10 | return '' 11 | } 12 | 13 | const {version} = await res.json() 14 | return version 15 | } 16 | 17 | function selectedWallet(name) { 18 | if (document.getElementById('remember-wallet__checkbox').checked) { 19 | localStorage.setItem(preferredWalletKey, name) 20 | } 21 | } 22 | 23 | (() => { 24 | getNodeVersion().then((version) => { 25 | document.getElementById('version').textContent = version 26 | }) 27 | const walletName = localStorage.getItem(preferredWalletKey) 28 | if (walletName) { 29 | document.getElementById(`${walletName}-link`).click() 30 | } 31 | })() 32 | 33 | -------------------------------------------------------------------------------- /html/ui/assets/vars.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --signum-blue: #00579d 3 | } 4 | -------------------------------------------------------------------------------- /html/ui/classic/README.md: -------------------------------------------------------------------------------- 1 | ## Signum Classic Wallet moved to another repository! 2 | 3 | In this folder it will be copied the files of the folder `src/` from the repository (signum-classic-wallet)[https://github.com/signum-network/signum-classic-wallet/]. 4 | 5 | The process is automated during a release creation. For more info check the `release.yml` workflow. 6 | 7 | If you want to install it manually, or update to a newer version run: `./update-classic.sh` 8 | -------------------------------------------------------------------------------- /html/ui/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/signum-network/signum-node/c064beb03264dcb7f49349dfd2b005511d19e1a2/html/ui/favicon.ico -------------------------------------------------------------------------------- /html/ui/legacy_api_doc_assets/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/signum-network/signum-node/c064beb03264dcb7f49349dfd2b005511d19e1a2/html/ui/legacy_api_doc_assets/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /html/ui/legacy_api_doc_assets/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/signum-network/signum-node/c064beb03264dcb7f49349dfd2b005511d19e1a2/html/ui/legacy_api_doc_assets/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /html/ui/legacy_api_doc_assets/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/signum-network/signum-node/c064beb03264dcb7f49349dfd2b005511d19e1a2/html/ui/legacy_api_doc_assets/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /html/ui/legacy_api_doc_assets/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/signum-network/signum-node/c064beb03264dcb7f49349dfd2b005511d19e1a2/html/ui/legacy_api_doc_assets/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /html/ui/phoenix/README.md: -------------------------------------------------------------------------------- 1 | ## Signum Phoenix wallet is maintained in anpother repository! 2 | 3 | In this folder it will be copied the files of the folder `src/` from the repository (Phoenix Wallet)[https://github.com/signum-network/phoenix/]. 4 | 5 | The process is automated during a release creation. For more info check the `release.yml` workflow. 6 | 7 | If you want to install it manually, or update to a newer Phoenix version run: `./update-phoenix.sh` 8 | -------------------------------------------------------------------------------- /neo-page/.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env: { browser: true, es2020: true }, 4 | extends: [ 5 | 'eslint:recommended', 6 | 'plugin:@typescript-eslint/recommended', 7 | 'plugin:react-hooks/recommended', 8 | ], 9 | ignorePatterns: ['dist', '.eslintrc.cjs'], 10 | parser: '@typescript-eslint/parser', 11 | plugins: ['react-refresh'], 12 | rules: { 13 | 'react-refresh/only-export-components': [ 14 | 'warn', 15 | { allowConstantExport: true }, 16 | ], 17 | }, 18 | } 19 | -------------------------------------------------------------------------------- /neo-page/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /neo-page/.nvmrc: -------------------------------------------------------------------------------- 1 | 20 2 | -------------------------------------------------------------------------------- /neo-page/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Signum Node 8 | 9 | 10 |
11 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /neo-page/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/signum-network/signum-node/c064beb03264dcb7f49349dfd2b005511d19e1a2/neo-page/public/favicon.ico -------------------------------------------------------------------------------- /neo-page/public/images/alias.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/signum-network/signum-node/c064beb03264dcb7f49349dfd2b005511d19e1a2/neo-page/public/images/alias.webp -------------------------------------------------------------------------------- /neo-page/public/images/api-icon.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/signum-network/signum-node/c064beb03264dcb7f49349dfd2b005511d19e1a2/neo-page/public/images/api-icon.webp -------------------------------------------------------------------------------- /neo-page/public/images/bg.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/signum-network/signum-node/c064beb03264dcb7f49349dfd2b005511d19e1a2/neo-page/public/images/bg.webp -------------------------------------------------------------------------------- /neo-page/public/images/cashback-cta.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/signum-network/signum-node/c064beb03264dcb7f49349dfd2b005511d19e1a2/neo-page/public/images/cashback-cta.webp -------------------------------------------------------------------------------- /neo-page/public/images/cashback.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/signum-network/signum-node/c064beb03264dcb7f49349dfd2b005511d19e1a2/neo-page/public/images/cashback.webp -------------------------------------------------------------------------------- /neo-page/public/images/developers-ballmer-min.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/signum-network/signum-node/c064beb03264dcb7f49349dfd2b005511d19e1a2/neo-page/public/images/developers-ballmer-min.gif -------------------------------------------------------------------------------- /neo-page/public/images/extension.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/signum-network/signum-node/c064beb03264dcb7f49349dfd2b005511d19e1a2/neo-page/public/images/extension.webp -------------------------------------------------------------------------------- /neo-page/public/images/mobile.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/signum-network/signum-node/c064beb03264dcb7f49349dfd2b005511d19e1a2/neo-page/public/images/mobile.webp -------------------------------------------------------------------------------- /neo-page/public/images/neo-wallet.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/signum-network/signum-node/c064beb03264dcb7f49349dfd2b005511d19e1a2/neo-page/public/images/neo-wallet.webp -------------------------------------------------------------------------------- /neo-page/public/images/phoenix.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/signum-network/signum-node/c064beb03264dcb7f49349dfd2b005511d19e1a2/neo-page/public/images/phoenix.webp -------------------------------------------------------------------------------- /neo-page/public/images/signum-neon-logo.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/signum-network/signum-node/c064beb03264dcb7f49349dfd2b005511d19e1a2/neo-page/public/images/signum-neon-logo.webp -------------------------------------------------------------------------------- /neo-page/public/images/signum-symbol.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/signum-network/signum-node/c064beb03264dcb7f49349dfd2b005511d19e1a2/neo-page/public/images/signum-symbol.webp -------------------------------------------------------------------------------- /neo-page/public/images/signum-translucid.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/signum-network/signum-node/c064beb03264dcb7f49349dfd2b005511d19e1a2/neo-page/public/images/signum-translucid.webp -------------------------------------------------------------------------------- /neo-page/public/images/woman-holding-hdd.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/signum-network/signum-node/c064beb03264dcb7f49349dfd2b005511d19e1a2/neo-page/public/images/woman-holding-hdd.webp -------------------------------------------------------------------------------- /neo-page/public/sounds/click.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/signum-network/signum-node/c064beb03264dcb7f49349dfd2b005511d19e1a2/neo-page/public/sounds/click.mp3 -------------------------------------------------------------------------------- /neo-page/public/sounds/intro.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/signum-network/signum-node/c064beb03264dcb7f49349dfd2b005511d19e1a2/neo-page/public/sounds/intro.mp3 -------------------------------------------------------------------------------- /neo-page/src/App.tsx: -------------------------------------------------------------------------------- 1 | import { Routes, Route } from "react-router-dom"; 2 | import { Layout } from "./components/Layout"; 3 | import { NoMatchPage } from "./pages/noMatch"; 4 | import { HomePage } from "./pages/home"; 5 | import { AppsPage } from "./pages/apps"; 6 | import { StatsPage } from "./pages/stats"; 7 | import { DocsPage } from "./pages/docs"; 8 | 9 | import "@fontsource/titillium-web/400.css"; 10 | import "@fontsource/titillium-web/600.css"; 11 | import "@fontsource/titillium-web/700.css"; 12 | import "@fontsource/titillium-web/900.css"; 13 | import "react-tooltip/dist/react-tooltip.css"; 14 | 15 | export default function App() { 16 | return ( 17 | 18 | }> 19 | } /> 20 | } /> 21 | } /> 22 | } /> 23 | } /> 24 | 25 | 26 | ); 27 | } 28 | -------------------------------------------------------------------------------- /neo-page/src/components/HeightChip/HeightChip.css.ts: -------------------------------------------------------------------------------- 1 | import { style } from "@vanilla-extract/css"; 2 | 3 | export const chip = style({ 4 | position: "relative", 5 | zIndex: 0, 6 | padding: "1rem", 7 | display: "flex", 8 | justifyContent: "center", 9 | fontSize: 14, 10 | }); 11 | 12 | export const frame = style({ 13 | // @ts-expect-error special arwes css 14 | "[data-name=bg]": { color: "hsl(180, 75%, 10%)" }, 15 | "[data-name=line]": { color: "hsl(180, 75%, 50%)" }, 16 | }); 17 | -------------------------------------------------------------------------------- /neo-page/src/components/HeightChip/HeightChip.tsx: -------------------------------------------------------------------------------- 1 | import { FrameSVGOctagon } from "@arwes/react-frames"; 2 | import { useBlockchainStatus } from "@/hooks/useBlockchainStatus"; 3 | import { formatNumber } from "@/utils/formatNumber"; 4 | import { frame, chip } from "./HeightChip.css"; 5 | 6 | export const HeightChip = () => { 7 | const { numberOfBlocks, isLoading } = useBlockchainStatus(); 8 | const formattedValue = formatNumber(numberOfBlocks); 9 | 10 | return ( 11 |
12 | 13 | {isLoading && Loading...} 14 | {!isLoading && Height: {formattedValue}} 15 | 16 | 17 |
18 | ); 19 | }; 20 | -------------------------------------------------------------------------------- /neo-page/src/components/HeightChip/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./HeightChip"; 2 | -------------------------------------------------------------------------------- /neo-page/src/components/Layout/components/Alerts/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./Alerts"; 2 | -------------------------------------------------------------------------------- /neo-page/src/components/Layout/components/Background/Background.css.ts: -------------------------------------------------------------------------------- 1 | import { style } from "@vanilla-extract/css"; 2 | 3 | export const defaultBG = style({ 4 | position: "fixed", 5 | left: 0, 6 | right: 0, 7 | top: 0, 8 | bottom: 0, 9 | background: `linear-gradient(rgba(0%,0%,0%,80%), rgba(0%,0%,0%,80%) ), url("/images/bg.webp")`, 10 | backgroundSize: "cover", 11 | backgroundPosition: "center", 12 | }); 13 | 14 | export const illuminatorContainer = style({ 15 | width: "100%", 16 | height: "100%", 17 | position: "relative", 18 | }); 19 | 20 | export const svgEffect = style({ 21 | width: "100%", 22 | height: "100%", 23 | position: "absolute", 24 | }); 25 | 26 | export const illuminator = style({ 27 | height: "100%", 28 | position: "absolute", 29 | top: 0, 30 | }); 31 | -------------------------------------------------------------------------------- /neo-page/src/components/Layout/components/Background/Background.tsx: -------------------------------------------------------------------------------- 1 | import { Fragment } from "react"; 2 | import { type AppTheme, Dots, MovingLines, Animator } from "@arwes/react"; 3 | import { Illuminator } from "@arwes/react-frames"; 4 | import * as classes from "./Background.css"; 5 | 6 | interface Props { 7 | theme: AppTheme; 8 | } 9 | 10 | export const Background = ({ theme }: Props) => { 11 | return ( 12 | 13 | 14 |
15 | 16 | 21 |
22 |
23 | 24 |
25 | 30 | 31 | 32 |
33 |
34 | ); 35 | }; 36 | -------------------------------------------------------------------------------- /neo-page/src/components/Layout/components/Background/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./Background"; 2 | -------------------------------------------------------------------------------- /neo-page/src/components/Layout/components/Footer/Footer.tsx: -------------------------------------------------------------------------------- 1 | import { githubLink } from "@/types"; 2 | 3 | export const Footer = () => ( 4 | 17 | ); 18 | -------------------------------------------------------------------------------- /neo-page/src/components/Layout/components/Footer/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Footer' -------------------------------------------------------------------------------- /neo-page/src/components/Layout/components/Header/Header.tsx: -------------------------------------------------------------------------------- 1 | import { useBlockchainStatus } from "@/hooks/useBlockchainStatus"; 2 | import { NavLinks } from "./components/NavLinks"; 3 | import { SocialLinks } from "./components/SocialLinks"; 4 | import * as classes from "./Header.css"; 5 | 6 | export const Header = () => { 7 | const { version, isLoading } = useBlockchainStatus(); 8 | 9 | return ( 10 |
11 |
12 | 17 | 18 | {!isLoading && {version}} 19 |
20 | 21 |
22 | 23 |
24 | 25 |
26 | 27 |
28 |
29 | ); 30 | }; 31 | -------------------------------------------------------------------------------- /neo-page/src/components/Layout/components/Header/components/NavLinks/NavLinks.css.ts: -------------------------------------------------------------------------------- 1 | import { style } from "@vanilla-extract/css"; 2 | import { recipe } from "@vanilla-extract/recipes"; 3 | import { theme } from "@/styles/theme"; 4 | 5 | export const contentContainer = style({ 6 | display: "flex", 7 | alignItems: "center", 8 | gap: 16, 9 | zIndex: 1, 10 | }); 11 | 12 | export const link = recipe({ 13 | base: { 14 | display: "flex", 15 | alignItems: "center", 16 | gap: 4, 17 | fontSize: "1.1rem", 18 | outline: "none", 19 | position: "relative", 20 | padding: "0.5rem 0.9rem", 21 | }, 22 | variants: { 23 | variant: { 24 | active: { color: theme.colors.primary.deco(25) }, 25 | inactive: { color: "rgba(255,255,255,0.5)" }, 26 | }, 27 | }, 28 | }); 29 | 30 | export const frame = style({ 31 | // @ts-expect-error special arwes css 32 | "[data-name=bg]": { color: "hsl(180, 75%, 10%)" }, 33 | "[data-name=line]": { color: "hsl(180, 75%, 50%)" }, 34 | }); 35 | -------------------------------------------------------------------------------- /neo-page/src/components/Layout/components/Header/components/NavLinks/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./NavLinks"; 2 | -------------------------------------------------------------------------------- /neo-page/src/components/Layout/components/Header/components/SocialLinks/SocialLinks.css.ts: -------------------------------------------------------------------------------- 1 | import { style } from "@vanilla-extract/css"; 2 | import { theme } from "@/styles/theme"; 3 | 4 | export const contentContainer = style({ 5 | display: "flex", 6 | alignItems: "center", 7 | gap: 16, 8 | zIndex: 1, 9 | }); 10 | 11 | export const avatar = style({ 12 | fontSize: 26, 13 | color: theme.colors.primary.deco(100), 14 | outline: "none", 15 | }); 16 | -------------------------------------------------------------------------------- /neo-page/src/components/Layout/components/Header/components/SocialLinks/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./SocialLinks"; 2 | -------------------------------------------------------------------------------- /neo-page/src/components/Layout/components/Header/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./Header"; 2 | -------------------------------------------------------------------------------- /neo-page/src/components/Layout/components/SyncAlert/SyncAlert.css.ts: -------------------------------------------------------------------------------- 1 | import { style } from "@vanilla-extract/css"; 2 | 3 | export const container = style({ 4 | position: "fixed", 5 | bottom: "3%", 6 | right: "3%", 7 | padding: "1rem", 8 | zIndex: 11, 9 | }); 10 | 11 | export const frame = style({ 12 | // @ts-expect-error special arwes css 13 | "[data-name=bg]": { 14 | color: "hsla(180, 75%, 10%, 80%)", 15 | }, 16 | "[data-name=line]": { color: "hsl(180, 75%, 75%)" }, 17 | backgroundSize: "cover", 18 | backgroundPosition: "center", 19 | overflow: "hidden", 20 | }); 21 | -------------------------------------------------------------------------------- /neo-page/src/components/Layout/components/SyncAlert/SyncAlert.tsx: -------------------------------------------------------------------------------- 1 | import { FrameSVGUnderline } from "@arwes/react-frames"; 2 | import { SyncChip } from "@/components/SyncChip"; 3 | import * as classes from "./SyncAlert.css"; 4 | 5 | export const SyncAlert = () => { 6 | return ( 7 |
8 | 9 | 10 |
11 | ); 12 | }; 13 | -------------------------------------------------------------------------------- /neo-page/src/components/Layout/components/SyncAlert/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./SyncAlert"; 2 | -------------------------------------------------------------------------------- /neo-page/src/components/Layout/index.tsx: -------------------------------------------------------------------------------- 1 | import { Outlet } from "react-router-dom"; 2 | import { theme } from "@/types"; 3 | import { Providers } from "@/providers"; 4 | import { Background } from "./components/Background"; 5 | import { Header } from "./components/Header"; 6 | import { Footer } from "./components/Footer"; 7 | import { Alerts } from "./components/Alerts"; 8 | import { SyncAlert } from "./components/SyncAlert"; 9 | 10 | export const Layout = () => { 11 | return ( 12 | 13 |
14 | 15 | 16 |
17 | 18 | 19 |
20 | 21 |
22 | 23 |
25 |
26 | ); 27 | }; 28 | -------------------------------------------------------------------------------- /neo-page/src/components/NeoChip/NeoChip.css.ts: -------------------------------------------------------------------------------- 1 | import { style } from "@vanilla-extract/css"; 2 | 3 | export const neoChip = style({ 4 | position: "relative", 5 | zIndex: 0, 6 | padding: "1rem 2rem", 7 | display: "flex", 8 | justifyContent: "center", 9 | }); 10 | 11 | export const frame = style({ 12 | // @ts-expect-error special arwes css 13 | "[data-name=bg]": { color: "hsl(180, 75%, 10%)" }, 14 | "[data-name=line]": { color: "hsl(180, 75%, 50%)" }, 15 | }); 16 | -------------------------------------------------------------------------------- /neo-page/src/components/NeoChip/NeoChip.tsx: -------------------------------------------------------------------------------- 1 | import { FrameSVGNefrex } from "@arwes/react-frames"; 2 | import { frame, neoChip } from "./NeoChip.css"; 3 | 4 | interface Props { 5 | label: string; 6 | } 7 | 8 | export const NeoChip = ({ label }: Props) => { 9 | return ( 10 |
11 | 12 | {label} 13 | 14 | 15 |
16 | ); 17 | }; 18 | -------------------------------------------------------------------------------- /neo-page/src/components/NeoChip/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./NeoChip.tsx"; 2 | -------------------------------------------------------------------------------- /neo-page/src/components/ShortcutCard/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./ShortcutCard"; 2 | -------------------------------------------------------------------------------- /neo-page/src/components/SyncChip/SyncChip.css.ts: -------------------------------------------------------------------------------- 1 | import { style } from "@vanilla-extract/css"; 2 | 3 | export const container = style({ 4 | position: "relative", 5 | zIndex: 11, 6 | padding: "1rem 2rem", 7 | overflow: "hidden", 8 | }); 9 | 10 | export const chip = style({ 11 | color: "hsl(152, 39%, 50%)", 12 | fontWeight: 900, 13 | margin: 0, 14 | textShadow: "0 0 15px hsl(152, 39%, 50%) ", 15 | zIndex: 100, 16 | width: "100%", 17 | textAlign: "center", 18 | display: "inline-block", 19 | }); 20 | 21 | export const frame = style({ 22 | // @ts-expect-error special arwes css 23 | "[data-name=bg]": { color: "hsl(152, 39%, 10%)" }, 24 | "[data-name=line]": { color: "hsl(152, 39%, 50%)" }, 25 | }); 26 | 27 | export const puff = style({ 28 | position: "absolute", 29 | width: "100%", 30 | height: "100%", 31 | top: 0, 32 | left: 0, 33 | }); 34 | -------------------------------------------------------------------------------- /neo-page/src/components/SyncChip/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./SyncChip"; 2 | -------------------------------------------------------------------------------- /neo-page/src/hooks/useFetchingInterval.ts: -------------------------------------------------------------------------------- 1 | import { useMemo } from "react"; 2 | import { localInterval, remoteInterval } from "@/types"; 3 | 4 | export const useFetchingInterval = () => { 5 | const interval = useMemo(() => { 6 | const webUrl = new URL(window.location.href); 7 | 8 | return webUrl.hostname === "localhost" || webUrl.hostname === "127.0.0.1" 9 | ? localInterval 10 | : remoteInterval; 11 | }, []); 12 | 13 | return interval; 14 | }; 15 | -------------------------------------------------------------------------------- /neo-page/src/hooks/useSound.ts: -------------------------------------------------------------------------------- 1 | import { useBleeps } from "@arwes/react"; 2 | import type { BleepsNames } from "@/types"; 3 | 4 | export const useSound = () => { 5 | const bleeps = useBleeps(); 6 | const playClickSound = () => bleeps.click?.play(); 7 | const playIntroSound = () => bleeps.intro?.play(); 8 | 9 | return { playClickSound, playIntroSound }; 10 | }; 11 | -------------------------------------------------------------------------------- /neo-page/src/hooks/useThirdPartyApps.ts: -------------------------------------------------------------------------------- 1 | import { useStore } from "@/states"; 2 | import useSWR from "swr"; 3 | 4 | export const useThirdPartyApps = () => { 5 | const interval = 240_000; 6 | 7 | const thirdPartyApps = useStore((state) => state.thirdPartyApps); 8 | const setThirdPartyApps = useStore((state) => state.setThirdPartyApps); 9 | 10 | useSWR( 11 | `getThirdPartyApps`, 12 | async () => { 13 | try { 14 | const response = await fetch( 15 | "https://signum-network.github.io/public-resources/third-party-apps.json" 16 | ); 17 | 18 | if (response.ok) { 19 | const result = await response.json(); 20 | setThirdPartyApps(result); 21 | } 22 | 23 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 24 | } catch (e: any) { 25 | console.error(e, "Error Fetching third party apps"); 26 | return null; 27 | } 28 | }, 29 | { dedupingInterval: interval, refreshInterval: interval } 30 | ); 31 | 32 | const isLoading = !thirdPartyApps.mainnet.length; 33 | 34 | return { thirdPartyApps, isLoading }; 35 | }; 36 | -------------------------------------------------------------------------------- /neo-page/src/main.tsx: -------------------------------------------------------------------------------- 1 | import { BrowserRouter } from "react-router-dom"; 2 | import ReactDOM from "react-dom/client"; 3 | import App from "./App.tsx"; 4 | 5 | // Arwes Web Framework UI requires react without strict mode 6 | ReactDOM.createRoot(document.getElementById("root")!).render( 7 | 8 | 9 | 10 | ); 11 | -------------------------------------------------------------------------------- /neo-page/src/pages/apps/index.tsx: -------------------------------------------------------------------------------- 1 | import { Fragment, useEffect } from "react"; 2 | import { MainApps } from "./sections/MainApps"; 3 | import { ThirdPartyApps } from "./sections/ThirdPartyApps"; 4 | 5 | export function AppsPage() { 6 | useEffect(() => { 7 | window.scrollTo(0, 0); 8 | }, []); 9 | 10 | return ( 11 | 12 | 13 | 14 | 15 | ); 16 | } 17 | -------------------------------------------------------------------------------- /neo-page/src/pages/apps/sections/MainApps/MainApps.css.ts: -------------------------------------------------------------------------------- 1 | import { style } from "@vanilla-extract/css"; 2 | 3 | export const titleContainer = style({ 4 | display: "flex", 5 | justifyContent: "space-between", 6 | alignItems: "center", 7 | "@media": { 8 | "(max-width: 600px)": { 9 | flexDirection: "column-reverse", 10 | justifyContent: "center", 11 | alignItems: "stretch", 12 | gap: "1rem", 13 | }, 14 | }, 15 | }); 16 | 17 | export const cardsContainer = style({ 18 | display: "flex", 19 | justifyContent: "flex-start", 20 | alignItems: "center", 21 | flexWrap: "wrap", 22 | gap: "4rem 1rem", 23 | marginTop: "3rem", 24 | }); 25 | -------------------------------------------------------------------------------- /neo-page/src/pages/apps/sections/MainApps/components/AppCard/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./AppCard"; 2 | -------------------------------------------------------------------------------- /neo-page/src/pages/apps/sections/MainApps/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./MainApps"; 2 | -------------------------------------------------------------------------------- /neo-page/src/pages/apps/sections/ThirdPartyApps/ThirpartyApps.css.ts: -------------------------------------------------------------------------------- 1 | import { style } from "@vanilla-extract/css"; 2 | 3 | export const titleContainer = style({ 4 | display: "flex", 5 | justifyContent: "space-between", 6 | }); 7 | 8 | export const loadingContainer = style({ 9 | position: "relative", 10 | height: "100vh", 11 | maxHeight: 500, 12 | marginTop: 25, 13 | }); 14 | -------------------------------------------------------------------------------- /neo-page/src/pages/apps/sections/ThirdPartyApps/components/LoadingIndicator/LoadingIndicator.tsx: -------------------------------------------------------------------------------- 1 | import { useState, useEffect } from "react"; 2 | import { Animator } from "@arwes/react-animator"; 3 | import { Dots } from "@arwes/react-bgs"; 4 | 5 | export const LoadingIndicator = () => { 6 | const [active, setActive] = useState(true); 7 | 8 | useEffect(() => { 9 | const iid = setInterval(() => setActive((active) => !active), 1200); 10 | return () => clearInterval(iid); 11 | }, []); 12 | 13 | return ( 14 | 15 | 21 | 22 | ); 23 | }; 24 | -------------------------------------------------------------------------------- /neo-page/src/pages/apps/sections/ThirdPartyApps/components/LoadingIndicator/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./LoadingIndicator"; 2 | -------------------------------------------------------------------------------- /neo-page/src/pages/apps/sections/ThirdPartyApps/components/ThirdPartyAppCard/AppCard.tsx: -------------------------------------------------------------------------------- 1 | import { useSound } from "@/hooks/useSound"; 2 | import type { ThirdPartyApp } from "@/types/thirdPartyApp"; 3 | import * as classes from "./AppCard.css"; 4 | 5 | export const ThirdPartyAppCard = ({ 6 | title, 7 | description, 8 | img, 9 | url, 10 | }: ThirdPartyApp) => { 11 | const { playClickSound } = useSound(); 12 | 13 | return ( 14 | 20 | {title} 21 | 22 |
23 |
{title}
24 |

{description}

25 |
26 |
27 | ); 28 | }; 29 | -------------------------------------------------------------------------------- /neo-page/src/pages/apps/sections/ThirdPartyApps/components/ThirdPartyAppCard/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./AppCard"; 2 | -------------------------------------------------------------------------------- /neo-page/src/pages/apps/sections/ThirdPartyApps/components/ViewSourceButton/ViewSourceButton.css.ts: -------------------------------------------------------------------------------- 1 | import { style } from "@vanilla-extract/css"; 2 | 3 | export const chip = style({ 4 | position: "relative", 5 | zIndex: 0, 6 | padding: "1rem", 7 | display: "flex", 8 | justifyContent: "center", 9 | fontSize: 14, 10 | }); 11 | 12 | export const frame = style({ 13 | // @ts-expect-error special arwes css 14 | "[data-name=bg]": { color: "hsl(180, 75%, 10%)" }, 15 | "[data-name=line]": { color: "hsl(180, 75%, 50%)" }, 16 | }); 17 | -------------------------------------------------------------------------------- /neo-page/src/pages/apps/sections/ThirdPartyApps/components/ViewSourceButton/ViewSourceButton.tsx: -------------------------------------------------------------------------------- 1 | import { FrameSVGOctagon } from "@arwes/react-frames"; 2 | import { frame, chip } from "./ViewSourceButton.css"; 3 | import { useSound } from "@/hooks/useSound"; 4 | 5 | export const ViewSourceButton = () => { 6 | const { playClickSound } = useSound(); 7 | 8 | return ( 9 | 15 | View Source 16 | 17 | 18 | ); 19 | }; 20 | -------------------------------------------------------------------------------- /neo-page/src/pages/apps/sections/ThirdPartyApps/components/ViewSourceButton/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./ViewSourceButton"; 2 | -------------------------------------------------------------------------------- /neo-page/src/pages/apps/sections/ThirdPartyApps/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./ThirdPartyApps"; 2 | -------------------------------------------------------------------------------- /neo-page/src/pages/docs/index.tsx: -------------------------------------------------------------------------------- 1 | import { Fragment, useEffect } from "react"; 2 | import { Title } from "./sections/Title"; 3 | import { Videotutorials } from "./sections/Videotutorials"; 4 | import { Wikis } from "./sections/Wikis"; 5 | import { Developer } from "./sections/Developer"; 6 | import { CommunityCta } from "./sections/CommunityCta"; 7 | 8 | export function DocsPage() { 9 | useEffect(() => { 10 | window.scrollTo(0, 0); 11 | }, []); 12 | 13 | return ( 14 | 15 | 16 | <Videotutorials /> 17 | <Wikis /> 18 | <Developer /> 19 | <CommunityCta /> 20 | </Fragment> 21 | ); 22 | } 23 | -------------------------------------------------------------------------------- /neo-page/src/pages/docs/sections/CommunityCta/CommunityCta.css.ts: -------------------------------------------------------------------------------- 1 | import { style } from "@vanilla-extract/css"; 2 | import { theme } from "@/styles/theme"; 3 | 4 | export const container = style({ 5 | display: "flex", 6 | flexDirection: "column", 7 | justifyContent: "center", 8 | alignItems: "center", 9 | }); 10 | 11 | export const title = style({ 12 | color: "white", 13 | fontSize: "2rem", 14 | textAlign: "center", 15 | }); 16 | 17 | export const btnContainer = style({ 18 | display: "flex", 19 | justifyContent: "center", 20 | alignItems: "center", 21 | gap: 8, 22 | marginTop: "1rem", 23 | }); 24 | 25 | export const button = style({ 26 | color: theme.colors.primary.deco(100), 27 | background: theme.colors.primary.deco(5), 28 | fontWeight: "bold", 29 | padding: "0.5rem", 30 | borderRadius: 4, 31 | fontSize: "1.1rem", 32 | cursor: "pointer", 33 | display: "flex", 34 | alignItems: "center", 35 | gap: 8, 36 | }); 37 | -------------------------------------------------------------------------------- /neo-page/src/pages/docs/sections/CommunityCta/CommunityCta.tsx: -------------------------------------------------------------------------------- 1 | import { Link } from "react-router-dom"; 2 | import { FaDiscord } from "react-icons/fa6"; 3 | import { defaultContainer } from "@/styles/containers.css"; 4 | import { discordLink } from "@/types"; 5 | import * as classes from "./CommunityCta.css"; 6 | 7 | export const CommunityCta = () => { 8 | return ( 9 | <section className={defaultContainer}> 10 | <div className={classes.container}> 11 | <img src="/images/signum-symbol.webp" alt="Signum Symbol" width={50} /> 12 | 13 | <h6 className={classes.title}> 14 | Do not know how to start? <br /> Do not worry, Join the community! 15 | </h6> 16 | </div> 17 | 18 | <div className={classes.btnContainer}> 19 | <Link to={discordLink} target="_blank" className={classes.button}> 20 | <FaDiscord /> Join the community 21 | </Link> 22 | </div> 23 | </section> 24 | ); 25 | }; 26 | -------------------------------------------------------------------------------- /neo-page/src/pages/docs/sections/CommunityCta/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./CommunityCta"; -------------------------------------------------------------------------------- /neo-page/src/pages/docs/sections/Developer/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./Developer"; 2 | -------------------------------------------------------------------------------- /neo-page/src/pages/docs/sections/Title/Title.tsx: -------------------------------------------------------------------------------- 1 | import { defaultContainer } from "@/styles/containers.css"; 2 | 3 | export const Title = () => { 4 | return ( 5 | <section className={defaultContainer}> 6 | <h1 style={{ color: "white", textAlign: "center" }}> 7 | Be a part of the <br /> sustainable crypto movement 8 | </h1> 9 | </section> 10 | ); 11 | }; 12 | -------------------------------------------------------------------------------- /neo-page/src/pages/docs/sections/Title/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./Title"; 2 | -------------------------------------------------------------------------------- /neo-page/src/pages/docs/sections/Videotutorials/Videotutorials.tsx: -------------------------------------------------------------------------------- 1 | import { NeoChip } from "@/components/NeoChip"; 2 | import { 3 | defaultContainer, 4 | defaultCardContainer, 5 | } from "@/styles/containers.css"; 6 | import { VideoTutorialCard } from "./components/VideoTutorialCard"; 7 | 8 | export const Videotutorials = () => { 9 | return ( 10 | <section className={defaultContainer}> 11 | <div style={{ display: "flex" }}> 12 | <NeoChip label="Videotutorials" /> 13 | </div> 14 | 15 | <div className={defaultCardContainer}> 16 | <VideoTutorialCard 17 | title="Setup Signum Account" 18 | href="https://www.youtube.com/watch?v=seUnm0GEwXY" 19 | /> 20 | 21 | <VideoTutorialCard 22 | title="Learn to Mine Signa" 23 | href="https://www.youtube.com/watch?v=zeIVCKN6Kpo" 24 | /> 25 | 26 | <VideoTutorialCard 27 | title="Manage your Signa commitment" 28 | href="https://www.youtube.com/watch?v=p-jEkv3aGAs" 29 | /> 30 | </div> 31 | </section> 32 | ); 33 | }; 34 | -------------------------------------------------------------------------------- /neo-page/src/pages/docs/sections/Videotutorials/components/VideoTutorialCard/VideoTutorialCard.tsx: -------------------------------------------------------------------------------- 1 | import { FaYoutube } from "react-icons/fa6"; 2 | import { useSound } from "@/hooks/useSound"; 3 | import * as classes from "./VideoTutorialCard.css"; 4 | 5 | interface Props { 6 | title: string; 7 | href: string; 8 | } 9 | 10 | export const VideoTutorialCard = ({ title, href }: Props) => { 11 | const { playClickSound } = useSound(); 12 | 13 | return ( 14 | <a 15 | href={href} 16 | onClick={playClickSound} 17 | target="_blank" 18 | className={classes.card} 19 | > 20 | <span className={classes.icon}> 21 | <FaYoutube /> 22 | </span> 23 | 24 | <span className={classes.title}>{title}</span> 25 | 26 | <p> 27 | <b>{"View Video >"}</b> 28 | </p> 29 | </a> 30 | ); 31 | }; 32 | -------------------------------------------------------------------------------- /neo-page/src/pages/docs/sections/Videotutorials/components/VideoTutorialCard/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./VideoTutorialCard"; 2 | -------------------------------------------------------------------------------- /neo-page/src/pages/docs/sections/Videotutorials/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./Videotutorials"; 2 | -------------------------------------------------------------------------------- /neo-page/src/pages/docs/sections/Wikis/components/WikiCard/WikiCard.css.ts: -------------------------------------------------------------------------------- 1 | import { style } from "@vanilla-extract/css"; 2 | import { theme } from "@/styles/theme"; 3 | 4 | export const card = style({ 5 | width: "24%", 6 | display: "flex", 7 | flexDirection: "column", 8 | alignItems: "center", 9 | padding: "2rem 1rem", 10 | border: "1px dashed", 11 | borderColor: "rgba(255, 255, 255, 0.3)", 12 | color: theme.colors.primary.deco(50), 13 | transition: "all 0.5s ease", 14 | outline: "none", 15 | boxShadow: "none", 16 | cursor: "pointer", 17 | textAlign: "center", 18 | ":hover": { 19 | background: "rgba(43, 237, 237, 0.2)", 20 | borderColor: "rgba(43, 237, 237, 0.3)", 21 | boxShadow: "0px 0px 20px 0px rgba(43, 237, 237, 0.5)", 22 | transform: "scale(1.05)", 23 | }, 24 | "@media": { 25 | "(max-width: 600px)": { 26 | width: "47%", 27 | marginBottom: "1rem", 28 | }, 29 | }, 30 | }); 31 | 32 | export const icon = style({ fontSize: "2rem" }); 33 | 34 | export const title = style({ 35 | margin: 0, 36 | fontSize: "1.1rem", 37 | fontWeight: "bold", 38 | textAlign: "center", 39 | }); 40 | -------------------------------------------------------------------------------- /neo-page/src/pages/docs/sections/Wikis/components/WikiCard/WikiCard.tsx: -------------------------------------------------------------------------------- 1 | import { FaLink } from "react-icons/fa6"; 2 | import { useSound } from "@/hooks/useSound"; 3 | import * as classes from "./WikiCard.css"; 4 | 5 | interface Props { 6 | title: string; 7 | description: string; 8 | href: string; 9 | } 10 | 11 | export const WikiCard = ({ title, description, href }: Props) => { 12 | const { playClickSound } = useSound(); 13 | 14 | return ( 15 | <a 16 | href={href} 17 | onClick={playClickSound} 18 | target="_blank" 19 | className={classes.card} 20 | > 21 | <span className={classes.icon}> 22 | <FaLink /> 23 | </span> 24 | 25 | <span className={classes.title}>{title}</span> 26 | <p>{description}</p> 27 | </a> 28 | ); 29 | }; 30 | -------------------------------------------------------------------------------- /neo-page/src/pages/docs/sections/Wikis/components/WikiCard/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./WikiCard"; 2 | -------------------------------------------------------------------------------- /neo-page/src/pages/home/index.tsx: -------------------------------------------------------------------------------- 1 | import { Fragment } from "react"; 2 | import { Welcome } from "./sections/Welcome"; 3 | import { HeroBanner } from "./sections/HeroBanner"; 4 | import { Shortcuts } from "./sections/Shortcuts"; 5 | import { PathCta } from "./sections/PathCta"; 6 | 7 | export function HomePage() { 8 | return ( 9 | <Fragment> 10 | <Welcome /> 11 | <HeroBanner /> 12 | <Shortcuts /> 13 | <PathCta /> 14 | </Fragment> 15 | ); 16 | } 17 | -------------------------------------------------------------------------------- /neo-page/src/pages/home/sections/HeroBanner/components/Alert/Alert.tsx: -------------------------------------------------------------------------------- 1 | import { FrameSVGCorners } from "@arwes/react-frames"; 2 | import { useSound } from "@/hooks/useSound"; 3 | import { defaultContainer } from "@/styles/containers.css"; 4 | import * as classes from "./Alert.css"; 5 | 6 | interface Props { 7 | show: boolean; 8 | title: string; 9 | href: string; 10 | cta: string; 11 | } 12 | 13 | export const Alert = ({ show, title, href, cta }: Props) => { 14 | const { playClickSound } = useSound(); 15 | 16 | if (!show) return null; 17 | 18 | return ( 19 | <section className={defaultContainer}> 20 | <div className={classes.banner}> 21 | {title} 22 | <a 23 | onClick={playClickSound} 24 | className={classes.button} 25 | href={href} 26 | target="_blank" 27 | > 28 | {cta} 29 | <FrameSVGCorners className={classes.buttonFrame} /> 30 | </a> 31 | <FrameSVGCorners className={classes.frame} /> 32 | </div> 33 | </section> 34 | ); 35 | }; 36 | -------------------------------------------------------------------------------- /neo-page/src/pages/home/sections/HeroBanner/components/Alert/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./Alert"; 2 | -------------------------------------------------------------------------------- /neo-page/src/pages/home/sections/HeroBanner/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./HeroBanner"; 2 | -------------------------------------------------------------------------------- /neo-page/src/pages/home/sections/PathCta/PathCta.css.ts: -------------------------------------------------------------------------------- 1 | import { style } from "@vanilla-extract/css"; 2 | import { theme } from "@/styles/theme"; 3 | 4 | export const container = style({ 5 | display: "flex", 6 | flexDirection: "column", 7 | justifyContent: "center", 8 | alignItems: "center", 9 | }); 10 | 11 | export const title = style({ 12 | color: "white", 13 | fontSize: "2rem", 14 | textAlign: "center", 15 | }); 16 | 17 | export const btnContainer = style({ 18 | display: "flex", 19 | justifyContent: "center", 20 | alignItems: "center", 21 | gap: 8, 22 | marginTop: "0.5rem", 23 | marginBottom: "2rem", 24 | }); 25 | 26 | export const button = style({ 27 | color: theme.colors.primary.deco(100), 28 | background: theme.colors.primary.deco(5), 29 | fontWeight: "bold", 30 | padding: "0.5rem", 31 | borderRadius: 4, 32 | fontSize: "1.1rem", 33 | cursor: "pointer", 34 | display: "flex", 35 | alignItems: "center", 36 | gap: 4, 37 | }); 38 | -------------------------------------------------------------------------------- /neo-page/src/pages/home/sections/PathCta/PathCta.tsx: -------------------------------------------------------------------------------- 1 | import { Link } from "react-router-dom"; 2 | import { FaList, FaBookOpen } from "react-icons/fa6"; 3 | import { defaultContainer } from "@/styles/containers.css"; 4 | import * as classes from "./PathCta.css"; 5 | 6 | export const PathCta = () => { 7 | return ( 8 | <section className={defaultContainer}> 9 | <div className={classes.container}> 10 | <img src="/images/signum-symbol.webp" alt="Signum Symbol" width={50} /> 11 | 12 | <h6 className={classes.title}> 13 | Blockchain Reimagined. <br /> Available now. 14 | </h6> 15 | </div> 16 | 17 | <div className={classes.btnContainer}> 18 | <Link to="/apps" className={classes.button}> 19 | <FaList /> Explore Apps 20 | </Link> 21 | 22 | <Link to="/docs" className={classes.button}> 23 | <FaBookOpen /> Read the docs 24 | </Link> 25 | </div> 26 | </section> 27 | ); 28 | }; 29 | -------------------------------------------------------------------------------- /neo-page/src/pages/home/sections/PathCta/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./PathCta"; 2 | -------------------------------------------------------------------------------- /neo-page/src/pages/home/sections/Shortcuts/Shortcuts.css.ts: -------------------------------------------------------------------------------- 1 | import { style } from "@vanilla-extract/css"; 2 | 3 | export const title = style({ 4 | margin: 0, 5 | fontSize: "1.5rem", 6 | textAlign: "center", 7 | "@media": { 8 | "(max-width: 600px)": { 9 | fontSize: "1.4rem", 10 | }, 11 | }, 12 | }); 13 | 14 | export const description = style({ 15 | fontWeight: "bold", 16 | fontSize: "1.2rem", 17 | textAlign: "center", 18 | "@media": { 19 | "(max-width: 600px)": { 20 | fontSize: "1rem", 21 | }, 22 | }, 23 | }); 24 | -------------------------------------------------------------------------------- /neo-page/src/pages/home/sections/Shortcuts/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./Shortcuts"; 2 | -------------------------------------------------------------------------------- /neo-page/src/pages/home/sections/Welcome/Welcome.tsx: -------------------------------------------------------------------------------- 1 | import { Suspense } from "react"; 2 | import { defaultContainer } from "@/styles/containers.css"; 3 | import { Spatial } from "./components/Spatial"; 4 | import * as classes from "./Welcome.css"; 5 | 6 | export const Welcome = () => { 7 | return ( 8 | <section className={defaultContainer}> 9 | <div className={classes.contentContainer}> 10 | <div className={classes.contentSection}> 11 | <h1 className={classes.title}> 12 | A eco-friendly blockchain ♻️ platform fulfilling all your needs 13 | </h1> 14 | 15 | <p className={classes.description}> 16 | Welcome to Signum, where innovation meets simplicity, and your 17 | business transforms into a smarter, more efficient powerhouse. 18 | </p> 19 | </div> 20 | 21 | <div className={classes.spatialContainer}> 22 | <Suspense> 23 | <Spatial /> 24 | </Suspense> 25 | </div> 26 | </div> 27 | </section> 28 | ); 29 | }; 30 | -------------------------------------------------------------------------------- /neo-page/src/pages/home/sections/Welcome/components/ActionCard/ActionCard.css.ts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/signum-network/signum-node/c064beb03264dcb7f49349dfd2b005511d19e1a2/neo-page/src/pages/home/sections/Welcome/components/ActionCard/ActionCard.css.ts -------------------------------------------------------------------------------- /neo-page/src/pages/home/sections/Welcome/components/ActionCard/ActionCard.tsx: -------------------------------------------------------------------------------- 1 | export const ActionCard = () => {}; 2 | -------------------------------------------------------------------------------- /neo-page/src/pages/home/sections/Welcome/components/ActionCard/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./ActionCard"; 2 | -------------------------------------------------------------------------------- /neo-page/src/pages/home/sections/Welcome/components/Spatial/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./Spatial"; 2 | -------------------------------------------------------------------------------- /neo-page/src/pages/home/sections/Welcome/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./Welcome"; 2 | -------------------------------------------------------------------------------- /neo-page/src/pages/noMatch/index.tsx: -------------------------------------------------------------------------------- 1 | import { Link } from "react-router-dom"; 2 | 3 | export function NoMatchPage() { 4 | return ( 5 | <div 6 | style={{ 7 | width: "100%", 8 | height: "75vh", 9 | display: "flex", 10 | justifyContent: "center", 11 | alignItems: "center", 12 | flexDirection: "column", 13 | overflow: "hidden", 14 | }} 15 | > 16 | <h2>Nothing to see here!</h2> 17 | <p> 18 | <Link to="/">Go to the home page</Link> 19 | </p> 20 | </div> 21 | ); 22 | } 23 | -------------------------------------------------------------------------------- /neo-page/src/pages/stats/index.tsx: -------------------------------------------------------------------------------- 1 | import { Fragment } from "react"; 2 | import { Stats } from "./sections/Stats"; 3 | 4 | export function StatsPage() { 5 | return ( 6 | <Fragment> 7 | <Stats /> 8 | </Fragment> 9 | ); 10 | } 11 | -------------------------------------------------------------------------------- /neo-page/src/pages/stats/sections/Stats/Stats.css.ts: -------------------------------------------------------------------------------- 1 | import { style } from "@vanilla-extract/css"; 2 | 3 | export const titleContainer = style({ 4 | display: "flex", 5 | justifyContent: "space-between", 6 | alignItems: "center", 7 | "@media": { 8 | "(max-width: 600px)": { 9 | flexDirection: "column-reverse", 10 | justifyContent: "center", 11 | alignItems: "stretch", 12 | gap: "1rem", 13 | }, 14 | }, 15 | }); 16 | 17 | export const contentContainer = style({ 18 | display: "flex", 19 | alignItems: "center", 20 | gap: 8, 21 | justifyContent: "space-between", 22 | }); 23 | 24 | export const genesisText = style({ 25 | color: "hsl(152, 39%, 60%)", 26 | }); 27 | 28 | export const syncChip = style({ 29 | display: "none", 30 | "@media": { 31 | "(max-width: 600px)": { 32 | display: "inline-block", 33 | }, 34 | }, 35 | }); 36 | -------------------------------------------------------------------------------- /neo-page/src/pages/stats/sections/Stats/components/KpiCard/KpiCard.css.ts: -------------------------------------------------------------------------------- 1 | import { style } from "@vanilla-extract/css"; 2 | import { recipe } from "@vanilla-extract/recipes"; 3 | import { theme } from "@/styles/theme"; 4 | 5 | export const card = style({ 6 | width: "25%", 7 | display: "flex", 8 | flexDirection: "column", 9 | justifyContent: "center", 10 | alignItems: "center", 11 | position: "relative", 12 | "@media": { 13 | "(max-width: 600px)": { 14 | width: "47%", 15 | marginBottom: "1rem", 16 | }, 17 | }, 18 | }); 19 | 20 | export const title = style({ 21 | color: theme.colors.primary.deco(50), 22 | textAlign: "center", 23 | fontWeight: 600, 24 | zIndex: 2, 25 | margin: 0, 26 | }); 27 | 28 | export const value = recipe({ 29 | base: { 30 | margin: 0, 31 | fontSize: "1.4rem", 32 | fontWeight: "bold", 33 | textAlign: "center", 34 | }, 35 | variants: { 36 | variant: { 37 | error: { color: theme.colors.warning.deco(50) }, 38 | success: { color: "hsl(152, 39%, 65%)" }, 39 | }, 40 | }, 41 | }); 42 | -------------------------------------------------------------------------------- /neo-page/src/pages/stats/sections/Stats/components/KpiCard/KpiCard.tsx: -------------------------------------------------------------------------------- 1 | import { formatNumber } from "@/utils/formatNumber"; 2 | import { BurnIndicator } from "./components/BurnIndicator"; 3 | import { LoadingIndicator } from "./components/LoadingIndicator"; 4 | import * as classes from "./KpiCard.css"; 5 | 6 | interface Props { 7 | title: string; 8 | value: number; 9 | isBurning?: boolean; 10 | isLoading: boolean; 11 | } 12 | 13 | export const KpiCard = ({ title, value, isBurning, isLoading }: Props) => { 14 | const formattedValue = formatNumber(value); 15 | 16 | return ( 17 | <div className={classes.card}> 18 | <span 19 | className={classes.value({ variant: isBurning ? "error" : "success" })} 20 | > 21 | {isLoading ? "Loading..." : formattedValue} 22 | </span> 23 | 24 | <p className={classes.title}>{title}</p> 25 | 26 | {isLoading && <LoadingIndicator />} 27 | 28 | {!!(isBurning && !isLoading) && <BurnIndicator />} 29 | </div> 30 | ); 31 | }; 32 | -------------------------------------------------------------------------------- /neo-page/src/pages/stats/sections/Stats/components/KpiCard/components/BurnIndicator/BurnIndicator.css.ts: -------------------------------------------------------------------------------- 1 | import { style } from "@vanilla-extract/css"; 2 | 3 | export const container = style({ 4 | position: "absolute", 5 | width: "100%", 6 | height: "70%", 7 | transform: "rotate(180deg)", 8 | top: 0, 9 | }); 10 | -------------------------------------------------------------------------------- /neo-page/src/pages/stats/sections/Stats/components/KpiCard/components/BurnIndicator/BurnIndicator.tsx: -------------------------------------------------------------------------------- 1 | import { Animator } from "@arwes/react-animator"; 2 | import { Puffs } from "@arwes/react-bgs"; 3 | import * as classes from "./BurnIndicator.css"; 4 | 5 | export const BurnIndicator = () => ( 6 | <Animator 7 | active 8 | duration={{ 9 | interval: 1, 10 | }} 11 | > 12 | <div className={classes.container}> 13 | <Puffs color="hsla(40, 81%, 50%, 0.5)" quantity={10} /> 14 | </div> 15 | </Animator> 16 | ); 17 | -------------------------------------------------------------------------------- /neo-page/src/pages/stats/sections/Stats/components/KpiCard/components/BurnIndicator/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./BurnIndicator"; 2 | -------------------------------------------------------------------------------- /neo-page/src/pages/stats/sections/Stats/components/KpiCard/components/LoadingIndicator/LoadingIndicator.tsx: -------------------------------------------------------------------------------- 1 | import { useState, useEffect } from "react"; 2 | import { Animator } from "@arwes/react-animator"; 3 | import { Dots } from "@arwes/react-bgs"; 4 | 5 | export const LoadingIndicator = () => { 6 | const [active, setActive] = useState(true); 7 | 8 | useEffect(() => { 9 | const iid = setInterval(() => setActive((active) => !active), 1200); 10 | return () => clearInterval(iid); 11 | }, []); 12 | 13 | return ( 14 | <Animator active={active} duration={{ enter: 0.75, exit: 0.75 }}> 15 | <Dots 16 | color="hsla(120, 100%, 75%, 0.1)" 17 | distance={10} 18 | size={5} 19 | origin="top" 20 | /> 21 | </Animator> 22 | ); 23 | }; 24 | -------------------------------------------------------------------------------- /neo-page/src/pages/stats/sections/Stats/components/KpiCard/components/LoadingIndicator/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./LoadingIndicator"; 2 | -------------------------------------------------------------------------------- /neo-page/src/pages/stats/sections/Stats/components/KpiCard/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./KpiCard"; 2 | -------------------------------------------------------------------------------- /neo-page/src/pages/stats/sections/Stats/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./Stats"; 2 | -------------------------------------------------------------------------------- /neo-page/src/providers/ThemeProvider.tsx: -------------------------------------------------------------------------------- 1 | import { Fragment } from "react"; 2 | import { 3 | AnimatorGeneralProvider, 4 | type BleepsProviderSettings, 5 | BleepsProvider, 6 | } from "@arwes/react"; 7 | import "@/styles/global.css"; 8 | import type { Props } from "./types"; 9 | 10 | const bleepsSettings: BleepsProviderSettings = { 11 | master: { volume: 0.75 }, 12 | bleeps: { 13 | // A transition bleep sound to play when the user enters the app. 14 | intro: { 15 | sources: [{ src: "/sounds/intro.mp3", type: "audio/mpeg" }], 16 | }, 17 | // An interactive bleep sound to play when user clicks. 18 | click: { 19 | sources: [{ src: "/sounds/click.mp3", type: "audio/mpeg" }], 20 | }, 21 | }, 22 | }; 23 | 24 | // Providers related to arwes framework goes here 25 | 26 | export function ThemeProvider({ children }: Props) { 27 | return ( 28 | <Fragment> 29 | <AnimatorGeneralProvider> 30 | <BleepsProvider {...bleepsSettings}>{children}</BleepsProvider> 31 | </AnimatorGeneralProvider> 32 | </Fragment> 33 | ); 34 | } 35 | -------------------------------------------------------------------------------- /neo-page/src/providers/index.tsx: -------------------------------------------------------------------------------- 1 | import { Fragment } from "react"; 2 | import type { Props } from "./types"; 3 | import { ThemeProvider } from "./ThemeProvider"; 4 | import { WalletProvider } from "./WalletProvider"; 5 | 6 | // Additional Providers will be added here 7 | export const Providers = ({ children }: Props) => { 8 | return ( 9 | <Fragment> 10 | <ThemeProvider> 11 | <WalletProvider>{children}</WalletProvider> 12 | </ThemeProvider> 13 | </Fragment> 14 | ); 15 | }; 16 | -------------------------------------------------------------------------------- /neo-page/src/providers/types.ts: -------------------------------------------------------------------------------- 1 | import { ReactNode } from "react"; 2 | 3 | export type Props = { 4 | children: ReactNode; 5 | }; 6 | -------------------------------------------------------------------------------- /neo-page/src/states/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./store"; 2 | export * from "./types"; 3 | -------------------------------------------------------------------------------- /neo-page/src/styles/containers.css.ts: -------------------------------------------------------------------------------- 1 | import { style } from "@vanilla-extract/css"; 2 | import { defaultMaxWidth } from "@/types"; 3 | 4 | export const defaultContainer = style({ 5 | width: "100%", 6 | maxWidth: defaultMaxWidth, 7 | margin: "auto", 8 | display: "flex", 9 | flexDirection: "column", 10 | padding: "1rem", 11 | marginBottom: "1rem", 12 | }); 13 | 14 | export const defaultCardContainer = style({ 15 | display: "flex", 16 | flexDirection: "row", 17 | justifyContent: "space-between", 18 | alignItems: "center", 19 | flexWrap: "wrap", 20 | gap: "2rem 0rem", 21 | marginTop: "2rem", 22 | "@media": { 23 | "(max-width: 600px)": { 24 | justifyContent: "center", 25 | gap: "1rem", 26 | }, 27 | }, 28 | }); 29 | -------------------------------------------------------------------------------- /neo-page/src/styles/global.css.ts: -------------------------------------------------------------------------------- 1 | import { globalStyle } from "@vanilla-extract/css"; 2 | import { createAppStylesBaseline } from "@arwes/react"; 3 | import { theme } from "./theme"; 4 | 5 | const stylesBaseline = createAppStylesBaseline(theme); 6 | 7 | Object.keys(stylesBaseline).forEach((styleName) => { 8 | globalStyle(styleName, stylesBaseline[styleName]); 9 | }); 10 | -------------------------------------------------------------------------------- /neo-page/src/styles/theme.ts: -------------------------------------------------------------------------------- 1 | import { type AppTheme as Theme, createAppTheme } from "@arwes/react"; 2 | 3 | const defaultFont = `"Titillium Web","Segoe UI Web (West European)","Segoe UI",-apple-system,BlinkMacSystemFont,Roboto,"Helvetica Neue",sans-serif`; 4 | 5 | const theme = createAppTheme({ 6 | settings: { 7 | hues: { 8 | primary: 180, 9 | secondary: 60, 10 | }, 11 | fontFamilies: { 12 | title: defaultFont, 13 | body: defaultFont, 14 | cta: defaultFont, 15 | input: defaultFont, 16 | code: "JetBrains Mono,Menlo,Monaco,Consolas,Courier New,monospace", 17 | }, 18 | }, 19 | }); 20 | 21 | export type { Theme }; 22 | export { theme }; 23 | -------------------------------------------------------------------------------- /neo-page/src/types/BleepsNames.ts: -------------------------------------------------------------------------------- 1 | export type BleepsNames = 2 | | "click" 3 | | "open" 4 | | "close" 5 | | "error" 6 | | "info" 7 | | "intro" 8 | | "content" 9 | | "type" 10 | | "assemble"; 11 | -------------------------------------------------------------------------------- /neo-page/src/types/defaultCashBackId.ts: -------------------------------------------------------------------------------- 1 | export const defaultCashBackId = "8952122635653861124"; 2 | -------------------------------------------------------------------------------- /neo-page/src/types/defaultMaxWidth.ts: -------------------------------------------------------------------------------- 1 | export const defaultMaxWidth = 1000; 2 | -------------------------------------------------------------------------------- /neo-page/src/types/fetchingIntervals.ts: -------------------------------------------------------------------------------- 1 | // 10 Seconds 2 | export const localInterval = 10_000; 3 | 4 | // 240 Seconds 5 | export const remoteInterval = 240_000; 6 | -------------------------------------------------------------------------------- /neo-page/src/types/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./defaultMaxWidth"; 2 | export * from "./BleepsNames"; 3 | export * from "./times"; 4 | export * from "./node"; 5 | export * from "./fetchingIntervals"; 6 | export * from "./thirdPartyApp"; 7 | export * from "./defaultCashBackId"; 8 | export * from "./socialLinks"; 9 | export * from "../styles/theme"; 10 | -------------------------------------------------------------------------------- /neo-page/src/types/node.ts: -------------------------------------------------------------------------------- 1 | export type Networks = "Signum" | "Signum-TESTNET"; 2 | -------------------------------------------------------------------------------- /neo-page/src/types/socialLinks.ts: -------------------------------------------------------------------------------- 1 | export const githubLink = "https://github.com/signum-network/signum-node"; 2 | export const twitterLink = "https://twitter.com/signum_official"; 3 | export const youtubeLink = "https://www.youtube.com/@SignumNetwork"; 4 | export const discordLink = "https://discord.com/invite/FATkyfNMxU"; 5 | -------------------------------------------------------------------------------- /neo-page/src/types/thirdPartyApp.ts: -------------------------------------------------------------------------------- 1 | export type ThirdPartyApp = { 2 | title: string; 3 | description: string; 4 | img: string; 5 | url: string; 6 | }; 7 | 8 | export type ThirdPartyAppStorage = { 9 | mainnet: ThirdPartyApp[]; 10 | testnet: ThirdPartyApp[]; 11 | }; 12 | -------------------------------------------------------------------------------- /neo-page/src/types/times.ts: -------------------------------------------------------------------------------- 1 | export const blockTimeInSeconds = 240; 2 | -------------------------------------------------------------------------------- /neo-page/src/utils/formatNumber.ts: -------------------------------------------------------------------------------- 1 | export const formatNumber = (value: number) => 2 | new Intl.NumberFormat("en-US").format(value); 3 | -------------------------------------------------------------------------------- /neo-page/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// <reference types="vite/client" /> 2 | -------------------------------------------------------------------------------- /neo-page/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2020", 4 | "useDefineForClassFields": true, 5 | "lib": ["ES2020", "DOM", "DOM.Iterable"], 6 | "module": "ESNext", 7 | "skipLibCheck": true, 8 | 9 | /* Alias */ 10 | "baseUrl": ".", 11 | "paths": { 12 | "@/*": ["./src/*"] 13 | }, 14 | 15 | /* Bundler mode */ 16 | "moduleResolution": "bundler", 17 | "allowImportingTsExtensions": true, 18 | "resolveJsonModule": true, 19 | "isolatedModules": true, 20 | "noEmit": true, 21 | "jsx": "react-jsx", 22 | 23 | /* Linting */ 24 | "strict": true, 25 | "noUnusedLocals": true, 26 | "noUnusedParameters": true, 27 | "noFallthroughCasesInSwitch": true 28 | }, 29 | "include": ["src"], 30 | "references": [{ "path": "./tsconfig.node.json" }] 31 | } 32 | -------------------------------------------------------------------------------- /neo-page/tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "composite": true, 4 | "skipLibCheck": true, 5 | "module": "ESNext", 6 | "moduleResolution": "bundler", 7 | "allowSyntheticDefaultImports": true 8 | }, 9 | "include": ["vite.config.ts"] 10 | } 11 | -------------------------------------------------------------------------------- /neo-page/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "vite"; 2 | import { vanillaExtractPlugin } from "@vanilla-extract/vite-plugin"; 3 | import react from "@vitejs/plugin-react-swc"; 4 | import path from "path"; 5 | 6 | // Learn about Vite config: https://vitejs.dev/config/ 7 | export default defineConfig({ 8 | plugins: [ 9 | react(), 10 | // Learn about Vanilla Extract Plugin: https://vanilla-extract.style/documentation/integrations/vite/ 11 | vanillaExtractPlugin({ 12 | identifiers: process.env.NODE_ENV === "development" ? "debug" : "short", 13 | }), 14 | ], 15 | resolve: { 16 | alias: { "@": path.resolve(__dirname, "./src") }, 17 | }, 18 | }); 19 | -------------------------------------------------------------------------------- /openapi/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | build 3 | openapitools.json 4 | -------------------------------------------------------------------------------- /openapi/openapitools.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "./node_modules/@openapitools/openapi-generator-cli/config.schema.json", 3 | "spaces": 2, 4 | "generator-cli": { 5 | "version": "6.0.1" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /openapi/parameters/account/account.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "account", 3 | "in": "query", 4 | "required": true, 5 | "allowEmptyValue": false, 6 | "description": "The account identifier", 7 | "schema": { 8 | "$ref": "../../schemas/address.json" 9 | } 10 | } -------------------------------------------------------------------------------- /openapi/parameters/alias/alias.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "alias", 3 | "in": "query", 4 | "allowEmptyValue": false, 5 | "description": "The related alias identifier", 6 | "schema": { 7 | "$ref": "../../schemas/aliasId.json" 8 | } 9 | } -------------------------------------------------------------------------------- /openapi/parameters/alias/tld.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tld", 3 | "in": "query", 4 | "description": "The TLD (namespace) of an alias. If not given the default TLD `signum` is applied.", 5 | "required": false, 6 | "schema": { 7 | "type": "string", 8 | "maxLength": "40", 9 | "pattern": "^[a-zA-Z0-9]{1,40}$" 10 | } 11 | } -------------------------------------------------------------------------------- /openapi/parameters/apiKey.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "apiKey", 3 | "in": "query", 4 | "allowEmptyValue": false, 5 | "description": "Any arbitrary string.<br/>\uD83D\uDD13 __Security Advice: Use a very strong and truly random key, or even disable admin operation entirely in your node config. Exposing admin operations is a security risk.__", 6 | "schema": { 7 | "type": "string" 8 | } 9 | } -------------------------------------------------------------------------------- /openapi/parameters/contract/at.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "at", 3 | "in": "query", 4 | "allowEmptyValue": false, 5 | "required": true, 6 | "description": "The contracts address.", 7 | "schema": { 8 | "$ref": "../../schemas/contractId.json" 9 | } 10 | } -------------------------------------------------------------------------------- /openapi/parameters/contract/includeDetails.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "includeDetails", 3 | "in": "query", 4 | "allowEmptyValue": false, 5 | "required": false, 6 | "description": "If set `true` more details are being returned (Default: `true`). Use `false` and payload can be reduced by approx. 40%", 7 | "schema": { 8 | "type": "boolean", 9 | "example": [ 10 | true, 11 | false 12 | ] 13 | } 14 | } -------------------------------------------------------------------------------- /openapi/parameters/description.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "description", 3 | "in": "query", 4 | "allowEmptyValue": false, 5 | "description": "This can be any arbitrary textual, json or even binary description. The maximum limit is 1000 characters, either text or binary (in hex form)", 6 | "schema": { 7 | "type": "string", 8 | "maxLength": 1000 9 | } 10 | } -------------------------------------------------------------------------------- /openapi/parameters/firstIndex.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "firstIndex", 3 | "in": "query", 4 | "description": "The first index to be returned. Use this for pagination.", 5 | "schema": { 6 | "type": "integer" 7 | } 8 | } -------------------------------------------------------------------------------- /openapi/parameters/lastIndex.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "lastIndex", 3 | "in": "query", 4 | "description": "The last index to be returned. Use this for pagination. If not set, at maximum 500 items beginning at `firstIndex` will be returned", 5 | "schema": { 6 | "type": "integer" 7 | } 8 | } -------------------------------------------------------------------------------- /openapi/parameters/timestamp.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "timestamp", 3 | "in": "query", 4 | "description": "The timestamp from which should be searched. Use this to get items only since that time. The time in seconds since first Block (Genesis) of the chain.", 5 | "schema": { 6 | "type": "integer", 7 | "format": "int64" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /openapi/parameters/token/asset.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "asset", 3 | "in": "query", 4 | "allowEmptyValue": false, 5 | "required": true, 6 | "description": "The related token identifier", 7 | "schema": { 8 | "$ref": "../../schemas/assetId.json" 9 | } 10 | } -------------------------------------------------------------------------------- /openapi/parameters/token/heightEnd.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "heightEnd", 3 | "in": "query", 4 | "allowEmptyValue": true, 5 | "required": false, 6 | "description": "Define the end height for trading information over a given period - if not given the current block is taken as end height", 7 | "schema": { 8 | "type": "integer" 9 | } 10 | } -------------------------------------------------------------------------------- /openapi/parameters/token/heightStart.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "heightStart", 3 | "in": "query", 4 | "allowEmptyValue": true, 5 | "required": false, 6 | "description": "Define the start height for trading information over a given period - if not given the last 360 blocks (around 24hrs) are taken as trading period", 7 | "schema": { 8 | "type": "integer" 9 | } 10 | } -------------------------------------------------------------------------------- /openapi/parameters/token/order.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "order", 3 | "in": "query", 4 | "allowEmptyValue": false, 5 | "required": true, 6 | "description": "An order identifier", 7 | "schema": { 8 | "$ref": "../../schemas/orderId.json" 9 | } 10 | } -------------------------------------------------------------------------------- /openapi/parameters/token/priceNQT.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "priceNQT", 3 | "in": "query", 4 | "allowEmptyValue": false, 5 | "required": true, 6 | "description": "The price in __planck per one token quantity__. To get the right Planck expression use this formula: `(priceNQT * 10^8) * 10^(decimals-8)`", 7 | "schema": { 8 | "type": "integer", 9 | "format": "int64" 10 | } 11 | } -------------------------------------------------------------------------------- /openapi/parameters/token/quantityQNT.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "quantityQNT", 3 | "in": "query", 4 | "allowEmptyValue": false, 5 | "required": true, 6 | "description": "The quantity of tokens expressed as an integer value, considering the number of decimals of the related token. If a token has two decimals the quantity value for 100 token is 10000.", 7 | "schema": { 8 | "$ref": "../../schemas/quantity.json" 9 | } 10 | } -------------------------------------------------------------------------------- /openapi/parameters/token/skipZeroVolume.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "skipZeroVolume", 3 | "in": "query", 4 | "allowEmptyValue": true, 5 | "required": false, 6 | "description": "If set `true` all zero volumes are excluded", 7 | "schema": { 8 | "type": "boolean", 9 | "example": [ 10 | true, 11 | false 12 | ] 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /openapi/parameters/transaction/amountNQT.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "amountNQT", 3 | "in": "query", 4 | "allowEmptyValue": false, 5 | "required": true, 6 | "description": "The amount expressed in Planck, i.e. 1 Signa = 10E8 Planck = 100000000 Planck", 7 | "schema": { 8 | "$ref": "../../schemas/amount.json", 9 | } 10 | } -------------------------------------------------------------------------------- /openapi/parameters/transaction/broadcast.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "broadcast", 3 | "in": "query", 4 | "allowEmptyValue": false, 5 | "description": "If set `false` the transaction will not be broadcast to the network", 6 | "schema": { 7 | "type": "boolean", 8 | "example": [true, false] 9 | } 10 | } -------------------------------------------------------------------------------- /openapi/parameters/transaction/deadline.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "deadline", 3 | "in": "query", 4 | "allowEmptyValue": false, 5 | "required": true, 6 | "description": "The deadline for how long the transaction may stay in the nodes mempool expressed in minutes until the transaction is being discarded", 7 | "schema": { 8 | "type": "integer", 9 | "format": "int32", 10 | "minimum": 1, 11 | "maximum": 1440, 12 | "example": [60, 120, 1440] 13 | } 14 | } -------------------------------------------------------------------------------- /openapi/parameters/transaction/encryptToSelfMessageData.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "encryptToSelfMessageData", 3 | "in": "query", 4 | "allowEmptyValue": false, 5 | "description": "It's possible to encrypt the data locally and send the encrypted data for maximum security. Together with this field you need to send `encryptToSelfMessageNonce` also.", 6 | "schema": { 7 | "type": "string", 8 | "maxLength": 1000 9 | } 10 | } -------------------------------------------------------------------------------- /openapi/parameters/transaction/encryptToSelfMessageNonce.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "encryptToSelfMessageNonce", 3 | "in": "query", 4 | "allowEmptyValue": false, 5 | "description": "It's possible to encrypt the data locally and send the encrypted data for maximum security. Together with this field you need to send `encryptToSelfMessageData` also.", 6 | "schema": { 7 | "type": "string" 8 | } 9 | } -------------------------------------------------------------------------------- /openapi/parameters/transaction/encryptedMessageData.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "encryptedMessageData", 3 | "in": "query", 4 | "allowEmptyValue": false, 5 | "description": "It's possible to encrypt the data locally and send the encrypted data for maximum security. Together with this field you need to send `encryptedMessageNonce` also.", 6 | "schema": { 7 | "type": "string", 8 | "maxLength": 1000 9 | } 10 | } -------------------------------------------------------------------------------- /openapi/parameters/transaction/encryptedMessageNonce.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "encryptedMessageNonce", 3 | "in": "query", 4 | "allowEmptyValue": false, 5 | "description": "It's possible to encrypt the data locally and send the encrypted data for maximum security. Together with this field you need to send `encryptedMessageData` also.", 6 | "schema": { 7 | "type": "string" 8 | } 9 | } -------------------------------------------------------------------------------- /openapi/parameters/transaction/feeNQT.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "feeNQT", 3 | "in": "query", 4 | "allowEmptyValue": false, 5 | "required": true, 6 | "description": "The fee for this transaction expressed in Planck, i.e. 0.01 Signa = 0.01 * 10E8 Planck = 1000000 Planck - The fee depends on the transaction type, but minimum fee is 0.01 Signa<br/>Read more about the fees [here](https://github.com/signum-network/SIPs/blob/master/SIP/sip-34.md)", 7 | "schema": { 8 | "$ref": "../../schemas/amount.json" 9 | } 10 | } -------------------------------------------------------------------------------- /openapi/parameters/transaction/message.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "message", 3 | "in": "query", 4 | "allowEmptyValue": false, 5 | "description": "It's possible to attach arbitrary data (in form of messages) to a transaction. The maximum limit is 1000 characters, either text or binary (in hex form)", 6 | "schema": { 7 | "type": "string", 8 | "maxLength": 1000 9 | } 10 | } -------------------------------------------------------------------------------- /openapi/parameters/transaction/messageIsText.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "messageIsText", 3 | "in": "query", 4 | "allowEmptyValue": false, 5 | "description": "Determines if the attached `message` is either text or binary data (hexadecimal string)", 6 | "schema": { 7 | "type": "boolean" 8 | }, 9 | "example": [true,false] 10 | } -------------------------------------------------------------------------------- /openapi/parameters/transaction/messageToEncrypt.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "messageToEncrypt", 3 | "in": "query", 4 | "allowEmptyValue": false, 5 | "description": "It's possible to attach P2P encrypted arbitrary data (in form of messages) to a transaction. The maximum limit is 1000 characters, either text or binary (in hex form).<br/> When using P2P encryption you need to pass `recipientPublicKey` also.<br/> \uD83D\uDD13 __Security Advice: When you use this you are sending the message in plain text to the node.__", 6 | "schema": { 7 | "type": "string", 8 | "maxLength": 1000 9 | } 10 | } -------------------------------------------------------------------------------- /openapi/parameters/transaction/messageToEncryptIsText.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "messageToEncryptIsText", 3 | "in": "query", 4 | "allowEmptyValue": false, 5 | "description": "Determines if the attached `messageToEncrypt` is either text or binary data (hexadecimal string)", 6 | "schema": { 7 | "type": "boolean" 8 | }, 9 | "example": [true,false] 10 | } -------------------------------------------------------------------------------- /openapi/parameters/transaction/messageToEncryptToSelf.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "messageToEncryptToSelf", 3 | "in": "query", 4 | "allowEmptyValue": false, 5 | "description": "When encrypting messages to yourself, you may want to use this field.", 6 | "schema": { 7 | "type": "string", 8 | "maxLength": 1000 9 | } 10 | } -------------------------------------------------------------------------------- /openapi/parameters/transaction/messageToEncryptToSelfIsText.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "messageToEncryptToSelfIsText", 3 | "in": "query", 4 | "allowEmptyValue": false, 5 | "description": "Determines if the attached `messageToEncryptToSelf` is either text or binary data (hexadecimal string)", 6 | "schema": { 7 | "type": "boolean" 8 | }, 9 | "example": [true,false] 10 | } -------------------------------------------------------------------------------- /openapi/parameters/transaction/publicKey.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "publicKey", 3 | "in": "query", 4 | "allowEmptyValue": false, 5 | "description": "The public key of the sending account.<br/>If you send this key instead of the `secretPhrase`, you get the _unsigned_ transaction back, which can then be signed locally. In that case the transaction is not being published.", 6 | "schema": { 7 | "$ref": "../../schemas/hash.json" 8 | } 9 | } -------------------------------------------------------------------------------- /openapi/parameters/transaction/recipient.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "recipient", 3 | "in": "query", 4 | "allowEmptyValue": false, 5 | "required": true, 6 | "description": "The recipients address. If the recipients address is `0` or `S-2222-2222-2222-22222` then you burn the tokens or coins sent to it.", 7 | "schema": { 8 | "$ref": "../../schemas/address.json" 9 | } 10 | } -------------------------------------------------------------------------------- /openapi/parameters/transaction/recipientPublicKey.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "recipientPublicKey", 3 | "in": "query", 4 | "allowEmptyValue": false, 5 | "description": "If you send a the recipients public key with a transaction you can automatically register (and activate) an account within the blockchain.", 6 | "schema": { 7 | "$ref": "../../schemas/hash.json" 8 | } 9 | } -------------------------------------------------------------------------------- /openapi/parameters/transaction/referencedTransactionFullHash.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "referencedTransactionFullHash", 3 | "in": "query", 4 | "allowEmptyValue": false, 5 | "description": "Using this field allows to make a transaction dependent on other transactions. This field will also be used for referencing carbon contracts", 6 | "schema": { 7 | "$ref": "../../schemas/hash.json" 8 | } 9 | } -------------------------------------------------------------------------------- /openapi/parameters/transaction/secretPhrase.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "secretPhrase", 3 | "in": "query", 4 | "allowEmptyValue": false, 5 | "description": "_Your_ secret passphrase.<br/>\uD83D\uDD13 __Security Advice: It's not recommended to pass this parameter to remote nodes unless you trust the node operator.__", 6 | "schema": { 7 | "type": "string" 8 | } 9 | } -------------------------------------------------------------------------------- /openapi/paths/admin/backupDB.json: -------------------------------------------------------------------------------- 1 | { 2 | "post": { 3 | "summary": "⚠️ Backup Database", 4 | "description": "This allows you to dump the database in a file. __Attention: This is a very long running operation__", 5 | "tags": [ 6 | "admin" 7 | ], 8 | "parameters": [ 9 | { 10 | "name": "filename", 11 | "in": "query", 12 | "required": true, 13 | "description": "The name of the resulting file", 14 | "schema": { 15 | "type": "string" 16 | } 17 | }, 18 | { 19 | "$ref": "../../parameters/apiKey.json" 20 | } 21 | ], 22 | "responses": { 23 | "200": { 24 | "$ref": "../../responses/empty.json" 25 | }, 26 | "500" : { 27 | "$ref": "../../responses/error.json" 28 | } 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /openapi/paths/admin/clearUnconfirmedTransactions.json: -------------------------------------------------------------------------------- 1 | { 2 | "post": { 3 | "summary": "⚠️ Clear Unconfirmed Transactions", 4 | "description": "Prunes unconfirmed transactions.", 5 | "tags": [ 6 | "admin" 7 | ], 8 | "parameters": [ 9 | { 10 | "$ref": "../../parameters/apiKey.json" 11 | } 12 | ], 13 | "responses": { 14 | "200": { 15 | "$ref": "../../responses/empty.json" 16 | }, 17 | "500" : { 18 | "$ref": "../../responses/error.json" 19 | } 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /openapi/paths/admin/fullReset.json: -------------------------------------------------------------------------------- 1 | { 2 | "post": { 3 | "summary": "⚠️ Full Node Reset", 4 | "description": "Resets the node and forces a resync.", 5 | "tags": [ 6 | "admin" 7 | ], 8 | "parameters": [ 9 | { 10 | "$ref": "../../parameters/apiKey.json" 11 | } 12 | ], 13 | "responses": { 14 | "200": { 15 | "$ref": "../../responses/empty.json" 16 | }, 17 | "500" : { 18 | "$ref": "../../responses/error.json" 19 | } 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /openapi/paths/getters/getAT.json: -------------------------------------------------------------------------------- 1 | { 2 | "get": { 3 | "summary": "Get Contract", 4 | "description": "Gets a specific smart contract", 5 | "tags": [ 6 | "contract" 7 | ], 8 | "parameters": [ 9 | { 10 | "$ref": "../../parameters/contract/at.json" 11 | }, 12 | { 13 | "$ref": "../../parameters/contract/includeDetails.json" 14 | } 15 | ], 16 | "responses": { 17 | "200": { 18 | "description": "Contract Response", 19 | "content": { 20 | "application/json": { 21 | "schema": { 22 | "$ref": "../../schemas/contract.json" 23 | } 24 | } 25 | } 26 | }, 27 | "500": { 28 | "$ref": "../../responses/error.json" 29 | } 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /openapi/paths/getters/getATDetails.json: -------------------------------------------------------------------------------- 1 | { 2 | "get": { 3 | "summary": "Get Contract History", 4 | "description": "Gets a specific contracts situation at a given moment in the past", 5 | "tags": [ 6 | "contract" 7 | ], 8 | "parameters": [ 9 | { 10 | "$ref": "../../parameters/contract/at.json" 11 | }, 12 | { 13 | "name": "height", 14 | "schema": { 15 | "type": "integer", 16 | "minimum": 0 17 | }, 18 | "in": "query", 19 | "description": "When set this block height the contracts situation at the given height will be returned" 20 | } 21 | ], 22 | "responses": { 23 | "200": { 24 | "description": "Contract Response", 25 | "content": { 26 | "application/json": { 27 | "schema": { 28 | "$ref": "../../schemas/contract.json" 29 | } 30 | } 31 | } 32 | }, 33 | "500": { 34 | "$ref": "../../responses/error.json" 35 | } 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /openapi/paths/getters/getAccountPublicKey.json: -------------------------------------------------------------------------------- 1 | { 2 | "get": { 3 | "summary": "Get Accounts Public Key", 4 | "description": "Get account public key. Useful to check if an account exists or is activated", 5 | "tags": [ 6 | "account" 7 | ], 8 | "parameters": [ 9 | { 10 | "$ref": "../../parameters/account/account.json" 11 | } 12 | ], 13 | "responses": { 14 | "200": { 15 | "description": "Account response", 16 | "content": { 17 | "application/json": { 18 | "schema": { 19 | "type": "object", 20 | "required": [ 21 | "publicKey" 22 | ], 23 | "properties": { 24 | "publicKey": { 25 | "$ref": "../../schemas/hash.json" 26 | } 27 | } 28 | } 29 | } 30 | } 31 | }, 32 | "500": { 33 | "$ref": "../../responses/error.json" 34 | } 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /openapi/paths/getters/getAccountSubscriptions.json: -------------------------------------------------------------------------------- 1 | { 2 | "get": { 3 | "summary": "Get Accounts Subscriptions", 4 | "description": "Get accounts running subscriptions, i.e. recurring payments. These are outgoing subscriptions. See [incoming subscriptions](#get-/api-requestType-getSubscriptionsToAccount)", 5 | "tags": [ 6 | "account", 7 | "payment" 8 | ], 9 | "parameters": [ 10 | { 11 | "$ref": "../../parameters/account/account.json" 12 | } 13 | ], 14 | "responses": { 15 | "200": { 16 | "description": "Subscription List response", 17 | "content": { 18 | "application/json": { 19 | "schema": { 20 | "type": "array", 21 | "required": [ 22 | "subscriptions" 23 | ], 24 | "items": { 25 | "$ref": "../../schemas/subscription.json" 26 | } 27 | } 28 | } 29 | } 30 | }, 31 | "500": { 32 | "$ref": "../../responses/error.json" 33 | } 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /openapi/paths/getters/getAskOrder.json: -------------------------------------------------------------------------------- 1 | { 2 | "get": { 3 | "summary": "Get Ask Order", 4 | "description": "Get a single ask order", 5 | "tags": [ 6 | "token" 7 | ], 8 | "parameters": [ 9 | { 10 | "$ref": "../../parameters/token/order.json" 11 | } 12 | ], 13 | "responses": { 14 | "200": { 15 | "description": "The requested order object", 16 | "content": { 17 | "application/json": { 18 | "schema": { 19 | "$ref": "../../schemas/order.json" 20 | } 21 | } 22 | } 23 | }, 24 | "500": { 25 | "$ref": "../../responses/error.json" 26 | } 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /openapi/paths/getters/getBidOrder.json: -------------------------------------------------------------------------------- 1 | { 2 | "get": { 3 | "summary": "Get Bid Order", 4 | "description": "Get a single bid order", 5 | "tags": [ 6 | "token" 7 | ], 8 | "parameters": [ 9 | { 10 | "$ref": "../../parameters/token/order.json" 11 | } 12 | ], 13 | "responses": { 14 | "200": { 15 | "description": "The requested order object", 16 | "content": { 17 | "application/json": { 18 | "schema": { 19 | "$ref": "../../schemas/order.json" 20 | } 21 | } 22 | } 23 | }, 24 | "500": { 25 | "$ref": "../../responses/error.json" 26 | } 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /openapi/paths/getters/getConstants.json: -------------------------------------------------------------------------------- 1 | { 2 | "get": { 3 | "summary": "Get Blockchain Parameters", 4 | "description": "Get this blockchains constant parameters ", 5 | "tags": [ 6 | "network" 7 | ], 8 | "responses": { 9 | "200": { 10 | "$ref": "../../responses/constants.json" 11 | } 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /openapi/paths/getters/getECBlock.json: -------------------------------------------------------------------------------- 1 | { 2 | "get": { 3 | "summary": "Get EC Block (Economic Clustering)", 4 | "description": "Get the reference for the block of an _economic cluster_ (EC) \uD83E\uDD37", 5 | "tags": [ 6 | "network" 7 | ], 8 | "parameters": [ 9 | { 10 | "name": "timestamp", 11 | "in": "query", 12 | "description": "The timestamp from which should be searched. It cannot be much in the past (about 15 seconds according the code)", 13 | "schema": { 14 | "type": "integer", 15 | "format": "int64" 16 | } 17 | } 18 | 19 | ], 20 | "responses": { 21 | "200": { 22 | "description": "The EC Block Reference", 23 | "content": { 24 | "application/json": { 25 | "schema": { 26 | "$ref": "../../schemas/ecblock.json" 27 | } 28 | } 29 | } 30 | }, 31 | "500": { 32 | "$ref": "../../responses/error.json" 33 | } 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /openapi/paths/getters/getSubscription.json: -------------------------------------------------------------------------------- 1 | { 2 | "get": { 3 | "summary": "Get Subscription", 4 | "description": "Get a subscription, i.e. recurring payment.", 5 | "tags": [ 6 | "payment" 7 | ], 8 | "parameters": [ 9 | { 10 | "name": "subscription", 11 | "in": "query", 12 | "allowEmptyValue": false, 13 | "required": true, 14 | "description": "The identifier of a subscription, i.e. its initial transaction id", 15 | "schema": { 16 | "type": "integer", 17 | "format": "int64" 18 | } 19 | } 20 | ], 21 | "responses": { 22 | "200": { 23 | "description": "Subscription response", 24 | "content": { 25 | "application/json": { 26 | "schema": { 27 | "$ref": "../../schemas/subscription.json" 28 | } 29 | } 30 | } 31 | }, 32 | "500": { 33 | "$ref": "../../responses/error.json" 34 | } 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /openapi/paths/getters/getSubscriptionsToAccount.json: -------------------------------------------------------------------------------- 1 | { 2 | "get": { 3 | "summary": "Get Recipient Subscriptions", 4 | "description": "Get subscriptions sent to an account/recipient, incoming subscriptions. See [subscriptions payments](#get-/api-requestType-getSubscriptionPayments)", 5 | "tags": [ 6 | "account", 7 | "payment" 8 | ], 9 | "parameters": [ 10 | { 11 | "$ref": "../../parameters/account/account.json" 12 | } 13 | ], 14 | "responses": { 15 | "200": { 16 | "description": "Subscription List response", 17 | "content": { 18 | "application/json": { 19 | "schema": { 20 | "type": "array", 21 | "required": [ 22 | "subscriptions" 23 | ], 24 | "items": { 25 | "$ref": "../../schemas/subscription.json" 26 | } 27 | } 28 | } 29 | } 30 | }, 31 | "500": { 32 | "$ref": "../../responses/error.json" 33 | } 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /openapi/paths/getters/getTime.json: -------------------------------------------------------------------------------- 1 | { 2 | "get": { 3 | "summary": "Get Chain Timestamp", 4 | "description": "Get the chains time stamp in seconds since Block 0", 5 | "tags": [ 6 | "network" 7 | ], 8 | "responses": { 9 | "200": { 10 | "description": "Time response", 11 | "content": { 12 | "application/json": { 13 | "schema": { 14 | "type": "object", 15 | "required": [ 16 | "time" 17 | ], 18 | "properties": { 19 | "time": { 20 | "description": "The time since beginning of the chain (Block 0)", 21 | "type": "integer", 22 | "format": "int64" 23 | } 24 | }, 25 | "example": { 26 | "time": 251558197, 27 | "requestProcessingTime": 1 28 | } 29 | } 30 | } 31 | } 32 | } 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /openapi/paths/parseTransaction.json: -------------------------------------------------------------------------------- 1 | { 2 | "post": { 3 | "summary": "Parse Transaction Bytes", 4 | "description": "Parses a _signed_ and/or _unsigned_ transaction bytes and returns as JSON object. This is merely a low-level API endpoint.", 5 | "tags": [ 6 | "utility" 7 | ], 8 | "parameters": [ 9 | { 10 | "name": "transactionBytes", 11 | "description": "The _signed_ and/or _unsigned_ transaction bytes in hexadecimal representation.", 12 | "required": true, 13 | "in": "query", 14 | "schema": { 15 | "$ref": "../schemas/hexString.json" 16 | } 17 | } 18 | ], 19 | "responses": { 20 | "200": { 21 | "description": "The parsed JSON object of the transaction", 22 | "content": { 23 | "application/json": { 24 | "schema": { 25 | "$ref": "../schemas/transaction.json" 26 | } 27 | } 28 | } 29 | }, 30 | "500": { 31 | "$ref": "../responses/error.json" 32 | } 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /openapi/paths/token/cancelBidOrder.json: -------------------------------------------------------------------------------- 1 | { 2 | "post": { 3 | "summary": "Cancel Bid Order (Cancel Buy)", 4 | "description": "Cancels a pending Bid Order. See also [Place Bid Order]() or [getBidOrders]()", 5 | "tags": [ 6 | "token" 7 | ], 8 | "parameters": [ 9 | { 10 | "$ref": "../../parameters/token/order.json" 11 | }, 12 | { 13 | "$ref": "../../parameters/transaction/feeNQT.json" 14 | }, 15 | { 16 | "$ref": "../../parameters/transaction/secretPhrase.json" 17 | }, 18 | { 19 | "$ref": "../../parameters/transaction/publicKey.json" 20 | }, 21 | { 22 | "$ref": "../../parameters/transaction/deadline.json" 23 | }, 24 | { 25 | "$ref": "../../parameters/transaction/broadcast.json" 26 | }, 27 | { 28 | "$ref": "../../parameters/transaction/referencedTransactionFullHash.json" 29 | } 30 | ], 31 | "responses": { 32 | "200": { 33 | "$ref": "../../responses/transaction.json" 34 | }, 35 | "500": { 36 | "$ref": "../../responses/error.json" 37 | } 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /openapi/responses/empty.json: -------------------------------------------------------------------------------- 1 | { 2 | "description": "Empty response. Operation executed successfully" 3 | } -------------------------------------------------------------------------------- /openapi/responses/error.json: -------------------------------------------------------------------------------- 1 | { 2 | "description": "Error Response - __IMPORTANT: Error Responses always come with a HTTP Status Code 200 \uD83E\uDD37__ ", 3 | "content": { 4 | "application/json": { 5 | "schema": { 6 | "type": "object", 7 | "required": [ 8 | "errorCode", 9 | "errorDescription" 10 | ], 11 | "example": { 12 | "errorCode": 5, 13 | "errorDescription": "Unknown account", 14 | "requestProcessingTime": 2 15 | }, 16 | "properties": { 17 | "errorDescription": { 18 | "type": "string", 19 | "description": "The error message indicating what the issue is" 20 | }, 21 | "errorCode": { 22 | "type": "integer", 23 | "description": "The internal error code" 24 | } 25 | } 26 | } 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /openapi/responses/transaction.json: -------------------------------------------------------------------------------- 1 | { 2 | "description": "Transaction Response", 3 | "content": { 4 | "application/json": { 5 | "schema": { 6 | "oneOf": [ 7 | { 8 | "$ref": "../schemas/signedTransaction.json" 9 | }, 10 | { 11 | "$ref": "../schemas/unsignedTransaction.json" 12 | } 13 | ] 14 | } 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /openapi/responses/transactionList.json: -------------------------------------------------------------------------------- 1 | { 2 | "description": "Transaction List Response", 3 | "content": { 4 | "application/json": { 5 | "schema": { 6 | "type": "object", 7 | "description": "A list of transactions.<br/>__Note__: For performance/stability reasons a node returns at maximum 500 items. All transaction query methods offer `firstIndex` and `lastIndex` to paginate through the transaction.", 8 | "required": [ 9 | "transactions" 10 | ], 11 | "properties": { 12 | "transactions" : { 13 | "type":"array", 14 | "items": { 15 | "$ref": "../schemas/signedTransaction.json" 16 | }, 17 | "maxLength": 500 18 | } 19 | } 20 | } 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /openapi/schemas/address.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "string", 3 | "oneOf": [ 4 | { 5 | "$ref": "./rsAddress.json" 6 | }, 7 | { 8 | "$ref": "./numericId.json" 9 | } 10 | ], 11 | "description": "The account identifier as numeric Id or Reed-Solomon encoded address, i.e. S-XXXX-XXXX-XXXX-XXXXX", 12 | "example": [ 13 | "S-5MS6-5FBY-74H4-9N4HS", 14 | "TS-QAJA-QW5Y-SWVP-4RVP4", 15 | "895212263565386113" 16 | ] 17 | } -------------------------------------------------------------------------------- /openapi/schemas/aliasId.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "integer", 3 | "format": "int64", 4 | "description": "The alias identifier", 5 | "required": true, 6 | "example": [ 7 | "4498738268646491227" 8 | ] 9 | } -------------------------------------------------------------------------------- /openapi/schemas/amount.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "integer", 3 | "format": "int64", 4 | "description": "The amount is always returned in Planck, that is Signa multiplied by 10E8", 5 | "example": [ 6 | "100000000", "1000000" 7 | ] 8 | } -------------------------------------------------------------------------------- /openapi/schemas/assetId.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "integer", 3 | "format": "int64", 4 | "description": "The token identifier", 5 | "required": true, 6 | "example": [ 7 | "12402415494995249540", "914948012239561046" 8 | ] 9 | } -------------------------------------------------------------------------------- /openapi/schemas/assetName.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "string", 3 | "description": "The name and symbol of this token. You can only use up to ten alphanumeric characters and no special chars", 4 | "pattern": "^a-zA-Z0-9{1,10}$" 5 | } 6 | -------------------------------------------------------------------------------- /openapi/schemas/blockId.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "integer", 3 | "format": "int64", 4 | "description": "The block identifier", 5 | "required": true, 6 | "example": [ 7 | "11398460215168332532" 8 | ] 9 | } -------------------------------------------------------------------------------- /openapi/schemas/contractAddress.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "string", 3 | "description": "The contracts address as Reed-Solomon encoded address, i.e. S-XXXX-XXXX-XXXX-XXXXX", 4 | "pattern": "^S|TS-[0-9A-Z]{4}[0-9A-Z]{4}[0-9A-Z]{4}[0-9A-Z]{5}$", 5 | "example": [ 6 | "\tS-LJ5Q-XTHJ-MY9B-2UPKR", 7 | "TS-DC2Q-C6GX-R56T-GHUN8" 8 | ] 9 | } -------------------------------------------------------------------------------- /openapi/schemas/contractData.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "integer", 3 | "format": "int64", 4 | "description": "The contract identifier", 5 | "required": true, 6 | } -------------------------------------------------------------------------------- /openapi/schemas/contractId.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "integer", 3 | "format": "int64", 4 | "description": "The numeric contract identifier", 5 | "required": true, 6 | "example": [ 7 | "848571112765341814","16380523479488112662" 8 | ] 9 | } -------------------------------------------------------------------------------- /openapi/schemas/ecblock.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "object", 3 | "required": [ 4 | "ecBlockId", 5 | "ecBlockHeight", 6 | "timestamp", 7 | ], 8 | "properties": { 9 | "ecBlockId": { 10 | "$ref": "./blockId.json" 11 | }, 12 | "ecBlockHeight": { 13 | "type": "integer", 14 | "description": "The block height" 15 | }, 16 | "timestamp": { 17 | "$ref": "./timestamp.json" 18 | } 19 | }, 20 | "example": { 21 | "ecBlockId": "11005421887713390160", 22 | "ecBlockHeight": 466561, 23 | "timestamp": 258400021, 24 | "requestProcessingTime": 1 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /openapi/schemas/hash.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "string", 3 | "pattern": "^[a-fA-F0-9]{64}$", 4 | "description": "A hexadecimal string of fixed size representing 256 Bit Hashes (SHA-256)", 5 | "example": "c213e4144ba84af94aae2458308fae1f0cb083870c8f3012eea58147f3b09d4a" 6 | } -------------------------------------------------------------------------------- /openapi/schemas/hexString.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "string", 3 | "pattern": "^[a-fA-F0-9]+$", 4 | "description": "A hexadecimal string of arbitrary length" 5 | } -------------------------------------------------------------------------------- /openapi/schemas/nextIndex.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "int32", 3 | "description": "Next index for pagination. When having more items, this field indicates which is the next `firstIndex` to be used. If not available, no more items are available also", 4 | "example": 10 5 | } -------------------------------------------------------------------------------- /openapi/schemas/numericId.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "integer", 3 | "format": "int64", 4 | "description": "The account identifier as numeric Id", 5 | "example": [ 6 | "895212263565386112","2402520554221019656" 7 | ] 8 | } -------------------------------------------------------------------------------- /openapi/schemas/orderId.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "integer", 3 | "format": "int64", 4 | "description": "The order identifier", 5 | "required": true, 6 | "example": [ 7 | "6954612694592252012" 8 | ] 9 | } -------------------------------------------------------------------------------- /openapi/schemas/orderPricePerQuantity.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "integer", 3 | "format": "int64", 4 | "description": "The price in __planck per one token quantity__. To get the right Planck expression use either `price` field or this formula: `(priceNQT * 10^8) * 10^(decimals-8)`" 5 | } -------------------------------------------------------------------------------- /openapi/schemas/quantity.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "integer", 3 | "format": "int64", 4 | "description": "The quantity is a tokens amount. It depends on the decimals a token supports, e.g. the quantity=100 of a token with 2 decimals is expressed as 10000", 5 | "example": [ 6 | "10000" 7 | ] 8 | } -------------------------------------------------------------------------------- /openapi/schemas/rsAddress.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "string", 3 | "description": "The account identifier as Reed-Solomon encoded address, i.e. S-XXXX-XXXX-XXXX-XXXXX", 4 | "pattern": "^S|TS-[0-9A-Z]{4}[0-9A-Z]{4}[0-9A-Z]{4}[0-9A-Z]{5}$", 5 | "example": [ 6 | "S-5MS6-5FBY-74H4-9N4HS", 7 | "TS-QAJA-QW5Y-SWVP-4RVP4" 8 | ] 9 | } -------------------------------------------------------------------------------- /openapi/schemas/timestamp.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "integer", 3 | "format": "int64", 4 | "description": "The time in seconds since first Block (Genesis) of the chain." 5 | } -------------------------------------------------------------------------------- /openapi/schemas/transactionId.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "integer", 3 | "format": "int64", 4 | "description": "The transaction identifier", 5 | "required": true, 6 | "example": [ 7 | "6954612694592252012" 8 | ] 9 | } -------------------------------------------------------------------------------- /resources/db/migration_h2_v2/V10_1__initial_transaction_block_id_index.sql: -------------------------------------------------------------------------------- 1 | create index if not exists "tx_block_id_index" on "transaction" ("block_id"); 2 | -------------------------------------------------------------------------------- /resources/db/migration_h2_v2/V10_2__alias_index.sql: -------------------------------------------------------------------------------- 1 | create index "alias_name_lower_tld_idx" 2 | on "alias" ("alias_name_lower" , "tld", "height" desc); 3 | 4 | create unique index "alias_id_height_idx" 5 | on "alias" ("id", "height"); 6 | 7 | -------------------------------------------------------------------------------- /resources/db/migration_h2_v2/V10_3__subscription_index.sql: -------------------------------------------------------------------------------- 1 | drop index if exists "subscription_id_height_idx"; 2 | create unique hash index "subscription_id_height_idx" 3 | on "subscription" ("id" asc, "height" desc); 4 | 5 | create hash index "subscription_id_latest_idx" 6 | on "subscription" ("id", "latest"); 7 | -------------------------------------------------------------------------------- /resources/db/migration_h2_v2/V10_4__at_index.sql: -------------------------------------------------------------------------------- 1 | drop index if exists "at_id_height_idx"; 2 | create unique hash index "at_id_height_idx" 3 | on "at" ("id" asc, "height" desc); 4 | -------------------------------------------------------------------------------- /resources/db/migration_h2_v2/V11__tx_index_sender_recipient.sql: -------------------------------------------------------------------------------- 1 | CREATE INDEX IF NOT EXISTS "transaction_recipient_id_sender_id_idx" ON "transaction" ("recipient_id", "sender_id"); 2 | -------------------------------------------------------------------------------- /resources/db/migration_h2_v2/V7_2__account_balance.sql: -------------------------------------------------------------------------------- 1 | // Kept because of JDBC flyway migration V7_3 - see src.brs.db.sql.migration 2 | 3 | create table "account_balance" 4 | ( 5 | "db_id" BIGINT generated by default as identity 6 | primary key, 7 | "id" BIGINT not null, 8 | "balance" BIGINT not null, 9 | "unconfirmed_balance" BIGINT not null, 10 | "forged_balance" BIGINT not null, 11 | "height" INTEGER not null, 12 | "latest" BOOLEAN default TRUE not null 13 | ); 14 | 15 | create index "account_balance_height_idx" 16 | on "account_balance" ("height"); 17 | 18 | create unique hash index "account_balance_id_height_idx" 19 | on "account_balance" ("id", "height"); 20 | 21 | create index "account_balance_id_latest_idx" 22 | on "account_balance" ("id", "latest"); 23 | -------------------------------------------------------------------------------- /resources/db/migration_h2_v2/V7_4__account_clean.sql: -------------------------------------------------------------------------------- 1 | // Kept because of JDBC flyway migration V7_3 2 | alter table "account" drop column if exists balance; 3 | alter table "account" drop column if exists unconfirmed_balance; 4 | alter table "account" drop column if exists forged_balance; 5 | -------------------------------------------------------------------------------- /resources/db/migration_mariadb/V10_1__initial_transaction_block_id_index.sql: -------------------------------------------------------------------------------- 1 | create index if not exists tx_block_id_index on transaction (block_id); 2 | -------------------------------------------------------------------------------- /resources/db/migration_mariadb/V10_2__alias_index.sql: -------------------------------------------------------------------------------- 1 | create index if not exists alias_name_lower_tld_idx 2 | on alias (alias_name_lower , tld, height desc); 3 | 4 | create unique index if not exists alias_id_height_idx 5 | on alias (id, height); 6 | 7 | -------------------------------------------------------------------------------- /resources/db/migration_mariadb/V10_3__subscription_index.sql: -------------------------------------------------------------------------------- 1 | 2 | drop index if exists subscription_id_height_idx on subscription; 3 | create unique index subscription_id_height_idx 4 | on subscription (id asc, height desc) using hash; 5 | 6 | create index if not exists subscription_id_latest_idx 7 | on subscription (id, latest) using hash; 8 | -------------------------------------------------------------------------------- /resources/db/migration_mariadb/V10_4__at_index.sql: -------------------------------------------------------------------------------- 1 | drop index if exists at_id_height_idx on at; 2 | create unique index at_id_height_idx 3 | on at (id asc, height desc) using hash; 4 | -------------------------------------------------------------------------------- /resources/db/migration_mariadb/V11__tx_index_sender_recipient.sql: -------------------------------------------------------------------------------- 1 | CREATE INDEX IF NOT EXISTS transaction_recipient_id_sender_id_idx ON transaction(recipient_id, sender_id); 2 | -------------------------------------------------------------------------------- /resources/db/migration_mariadb/V12__account_balance_index.sql: -------------------------------------------------------------------------------- 1 | DROP INDEX IF EXISTS account_asset_assetid_idx ON account_asset; 2 | CREATE INDEX IF NOT EXISTS account_asset_assetid_latest_idx ON account_asset (account_id, asset_id, latest); -------------------------------------------------------------------------------- /resources/db/migration_mariadb/V2__indirect_incoming.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE IF NOT EXISTS indirect_incoming 2 | ( 3 | db_id bigint(20) AUTO_INCREMENT, 4 | account_id bigint(20) NOT NULL, 5 | transaction_id bigint(20) NOT NULL, 6 | height INT NOT NULL, 7 | PRIMARY KEY (db_id) 8 | ); 9 | CREATE UNIQUE INDEX indirect_incoming_db_id_uindex ON indirect_incoming (account_id, transaction_id); -------------------------------------------------------------------------------- /resources/db/migration_mariadb/V3__indirect_incoming_index.sql: -------------------------------------------------------------------------------- 1 | CREATE INDEX IF NOT EXISTS indirect_incoming_index ON indirect_incoming (height); -------------------------------------------------------------------------------- /resources/db/migration_mariadb/V4__subscription_index.sql: -------------------------------------------------------------------------------- 1 | CREATE INDEX IF NOT EXISTS subscription_time_next_index ON subscription (time_next); -------------------------------------------------------------------------------- /resources/db/migration_mariadb/V5_2__at_ap_code.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE at MODIFY COLUMN ap_code blob NULL; 2 | -------------------------------------------------------------------------------- /resources/db/migration_mariadb/V5__at_code_hash.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE at ADD ap_code_hash_id BIGINT; 2 | 3 | CREATE INDEX at_ap_code_hash_id_index ON at (ap_code_hash_id); -------------------------------------------------------------------------------- /resources/db/migration_mariadb/V6_1__indirect_upgrade.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE indirect_incoming ADD amount bigint(20) DEFAULT '0'; 2 | ALTER TABLE indirect_incoming ADD quantity bigint(20) DEFAULT '0'; 3 | -------------------------------------------------------------------------------- /resources/db/migration_mariadb/V6_2__tx_indices.sql: -------------------------------------------------------------------------------- 1 | CREATE INDEX IF NOT EXISTS tx_sender_type ON transaction (sender_id, type); 2 | CREATE INDEX IF NOT EXISTS indirect_incoming_id_index ON indirect_incoming (account_id); -------------------------------------------------------------------------------- /resources/db/migration_mariadb/V6_3__subscription_latest_index.sql: -------------------------------------------------------------------------------- 1 | CREATE INDEX IF NOT EXISTS subscription_latest_index ON subscription (latest); 2 | -------------------------------------------------------------------------------- /resources/db/migration_mariadb/V6__asset_upgrade.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE asset ADD mintable tinyint(1) NOT NULL DEFAULT '0'; 2 | -------------------------------------------------------------------------------- /resources/db/migration_mariadb/V7_1__smart_ats.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE IF NOT EXISTS at_map (db_id bigint(20) NOT NULL AUTO_INCREMENT, 2 | at_id bigint(20) NOT NULL, key1 bigint(20) NOT NULL, key2 bigint(20), value bigint(20), 3 | height INT NOT NULL, latest BOOLEAN NOT NULL DEFAULT TRUE, 4 | PRIMARY KEY (`db_id`)); 5 | 6 | -------------------------------------------------------------------------------- /resources/db/migration_mariadb/V7_2__account_balance.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE IF NOT EXISTS account_balance (db_id bigint(20) NOT NULL AUTO_INCREMENT, 2 | id bigint(20) NOT NULL, 3 | balance bigint(20) NOT NULL, 4 | unconfirmed_balance bigint(20) NOT NULL, 5 | forged_balance bigint(20) NOT NULL, 6 | height INT NOT NULL, latest BOOLEAN NOT NULL DEFAULT TRUE, 7 | PRIMARY KEY (`db_id`)); 8 | 9 | CREATE INDEX IF NOT EXISTS account_balance_id_balance_height_idx ON account_balance (id, balance, height DESC); 10 | -------------------------------------------------------------------------------- /resources/db/migration_mariadb/V7_4__account_clean.sql: -------------------------------------------------------------------------------- 1 | 2 | ALTER TABLE account DROP COLUMN IF EXISTS balance; 3 | ALTER TABLE account DROP COLUMN IF EXISTS unconfirmed_balance; 4 | ALTER TABLE account DROP COLUMN IF EXISTS forged_balance; 5 | -------------------------------------------------------------------------------- /resources/db/migration_mariadb/V7_5__index_fix.sql: -------------------------------------------------------------------------------- 1 | DROP INDEX IF EXISTS asset_transfer_id_idx ON asset_transfer; 2 | 3 | CREATE INDEX IF NOT EXISTS asset_transfer_id_idx ON asset_transfer (id); 4 | -------------------------------------------------------------------------------- /resources/db/migration_mariadb/V7_6__balance_index.sql: -------------------------------------------------------------------------------- 1 | DROP INDEX IF EXISTS account_id_balance_height_idx ON account; 2 | 3 | CREATE INDEX IF NOT EXISTS account_balance_id_latest_idx ON account_balance(id, latest); 4 | -------------------------------------------------------------------------------- /resources/db/migration_mariadb/V7_7__index_clean.sql: -------------------------------------------------------------------------------- 1 | DROP INDEX IF EXISTS account_balance_id_balance_height_idx ON account_balance; 2 | -------------------------------------------------------------------------------- /resources/db/migration_mariadb/V7_8__add_indices.sql: -------------------------------------------------------------------------------- 1 | CREATE INDEX IF NOT EXISTS transaction_type_subtype_idx ON transaction(type, subtype) using btree; 2 | 3 | CREATE UNIQUE INDEX IF NOT EXISTS account_balance_id_height_idx ON account_balance(id, height); 4 | -------------------------------------------------------------------------------- /resources/db/migration_mariadb/V7__cashback_and_burn.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE transaction ADD cash_back_id BIGINT DEFAULT '0'; 2 | 3 | CREATE INDEX tx_cash_back_index ON transaction (cash_back_id); 4 | 5 | ALTER TABLE block 6 | ADD total_fee_cash_back BIGINT DEFAULT '0', 7 | ADD total_fee_burnt BIGINT DEFAULT '0'; 8 | -------------------------------------------------------------------------------- /resources/db/migration_mariadb/V8_1__generator_index.sql: -------------------------------------------------------------------------------- 1 | CREATE INDEX IF NOT EXISTS block_generator_id_height_idx ON block(generator_id, height) using btree; 2 | -------------------------------------------------------------------------------- /resources/db/migration_mariadb/V8_2__at_state_index.sql: -------------------------------------------------------------------------------- 1 | CREATE INDEX IF NOT EXISTS at_state_id_latest_idx ON at_state(at_id, latest) using btree; 2 | -------------------------------------------------------------------------------- /resources/db/migration_mariadb/V8__alias_tld.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE alias ADD tld BIGINT DEFAULT 0; 2 | -------------------------------------------------------------------------------- /resources/db/migration_mariadb/V9__ats_mediumblob.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE block CHANGE COLUMN ats ats MEDIUMBLOB NULL AFTER nonce; 2 | -------------------------------------------------------------------------------- /resources/db/migration_postgres/V11__tx_index_sender_recipient.sql: -------------------------------------------------------------------------------- 1 | CREATE INDEX IF NOT EXISTS transaction_recipient_id_sender_id_idx ON transaction (recipient_id, sender_id); 2 | -------------------------------------------------------------------------------- /resources/db/migration_postgres/V12__account_balance_index.sql: -------------------------------------------------------------------------------- 1 | DROP INDEX IF EXISTS idx_16404_account_asset_assetid_idx; 2 | CREATE INDEX IF NOT EXISTS idx_16404_account_asset_assetid_latest_idx ON account_asset (account_id, asset_id, latest); -------------------------------------------------------------------------------- /resources/db/migration_sqlite/V11__tx_index_sender_recipient.sql: -------------------------------------------------------------------------------- 1 | CREATE INDEX IF NOT EXISTS transaction_recipient_id_sender_id_idx ON "transaction" (recipient_id, sender_id); 2 | -------------------------------------------------------------------------------- /resources/db/migration_sqlite/V12__account_balance_index.sql: -------------------------------------------------------------------------------- 1 | DROP INDEX IF EXISTS account_asset_assetid_idx; 2 | CREATE INDEX IF NOT EXISTS account_asset_assetid_latest_idx ON account_asset (account_id, asset_id, latest); -------------------------------------------------------------------------------- /resources/images/signum_overlay_logo.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/signum-network/signum-node/c064beb03264dcb7f49349dfd2b005511d19e1a2/resources/images/signum_overlay_logo.ico -------------------------------------------------------------------------------- /resources/images/signum_overlay_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/signum-network/signum-node/c064beb03264dcb7f49349dfd2b005511d19e1a2/resources/images/signum_overlay_logo.png -------------------------------------------------------------------------------- /resources/images/signum_testnet_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/signum-network/signum-node/c064beb03264dcb7f49349dfd2b005511d19e1a2/resources/images/signum_testnet_logo.png -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * This settings file was generated by the Gradle 'init' task. 3 | * 4 | * The settings file is used to specify which projects to include in your build. 5 | * In a single project build this file can be empty or even removed. 6 | * 7 | * Detailed information about configuring a multi-project build in Gradle can be found 8 | * in the user guide at https://docs.gradle.org/4.4.1/userguide/multi_project_builds.html 9 | */ 10 | 11 | rootProject.name = 'signum-node' 12 | -------------------------------------------------------------------------------- /src/brs/Genesis.java: -------------------------------------------------------------------------------- 1 | package brs; 2 | 3 | public final class Genesis { 4 | 5 | public static final long GENESIS_BLOCK_ID = 3444294670862540038L; 6 | public static final long CREATOR_ID = 0L; 7 | 8 | private static final byte[] CREATOR_PUBLIC_KEY = { 9 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 11 | }; 12 | 13 | private static final byte[] GENESIS_BLOCK_SIGNATURE = new byte[]{ 14 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 18 | }; 19 | 20 | public static byte[] getCreatorPublicKey() { 21 | return CREATOR_PUBLIC_KEY.clone(); 22 | } 23 | 24 | public static byte[] getGenesisBlockSignature() { 25 | return GENESIS_BLOCK_SIGNATURE.clone(); 26 | } 27 | 28 | private Genesis() {} // never 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/brs/at/AtBlock.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014 CIYAM Developers 3 | 4 | Distributed under the MIT/X11 software license, please refer to the file license.txt 5 | in the root project directory or http://www.opensource.org/licenses/mit-license.php. 6 | 7 | */ 8 | package brs.at; 9 | 10 | public class AtBlock { 11 | private final long totalFees; 12 | private final long totalAmount; 13 | private final byte[] bytesForBlock; 14 | 15 | AtBlock(long totalFees, long totalAmount, byte[] bytesForBlock) { 16 | this.totalFees = totalFees; 17 | this.totalAmount = totalAmount; 18 | this.bytesForBlock = bytesForBlock; 19 | } 20 | 21 | public long getTotalFees() { 22 | return totalFees; 23 | } 24 | 25 | public long getTotalAmount() { 26 | return totalAmount; 27 | } 28 | 29 | public byte[] getBytesForBlock() { 30 | return bytesForBlock; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/brs/at/AtException.java: -------------------------------------------------------------------------------- 1 | package brs.at; 2 | 3 | public class AtException extends Exception { 4 | private static final long serialVersionUID = 1L; 5 | 6 | public AtException(String message) { 7 | super(message); 8 | } 9 | 10 | public AtException(String message, Throwable cause) { 11 | super(message, cause); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/brs/db/BlockDb.java: -------------------------------------------------------------------------------- 1 | package brs.db; 2 | 3 | import brs.Block; 4 | import brs.SignumException; 5 | import brs.schema.tables.records.BlockRecord; 6 | import org.jooq.DSLContext; 7 | 8 | public interface BlockDb extends Table { 9 | Block findBlock(long blockId); 10 | 11 | boolean hasBlock(long blockId); 12 | 13 | long findBlockIdAtHeight(int height); 14 | 15 | Block findBlockAtHeight(int height); 16 | 17 | Block findLastBlock(); 18 | 19 | Block findLastBlock(int timestamp); 20 | 21 | Block loadBlock(BlockRecord r) throws SignumException.ValidationException; 22 | 23 | void saveBlock(DSLContext ctx, Block block); 24 | 25 | // relying on cascade triggers in the database to delete the transactions for all deleted blocks 26 | void deleteBlocksFrom(long blockId); 27 | 28 | void deleteAll(boolean force); 29 | } 30 | -------------------------------------------------------------------------------- /src/brs/db/DerivedTable.java: -------------------------------------------------------------------------------- 1 | package brs.db; 2 | 3 | public interface DerivedTable extends Table { 4 | String getTable(); 5 | 6 | void rollback(int height); 7 | 8 | void truncate(); 9 | 10 | void trim(int height); 11 | 12 | void finish(); 13 | } 14 | -------------------------------------------------------------------------------- /src/brs/db/PeerDb.java: -------------------------------------------------------------------------------- 1 | package brs.db; 2 | 3 | import java.util.Collection; 4 | import java.util.List; 5 | 6 | public interface PeerDb extends Table { 7 | List<String> loadPeers(); 8 | 9 | void deletePeers(Collection<String> peers); 10 | 11 | void addPeers(Collection<String> peers); 12 | } 13 | -------------------------------------------------------------------------------- /src/brs/db/SignumKey.java: -------------------------------------------------------------------------------- 1 | package brs.db; 2 | 3 | import org.jooq.Record; 4 | 5 | public interface SignumKey { 6 | 7 | interface Factory<T> { 8 | SignumKey newKey(T t); 9 | 10 | SignumKey newKey(Record rs); 11 | } 12 | 13 | long[] getPKValues(); 14 | 15 | interface LongKeyFactory<T> extends Factory<T> { 16 | @Override 17 | SignumKey newKey(Record rs); 18 | 19 | SignumKey newKey(long id); 20 | 21 | } 22 | 23 | interface LinkKeyFactory<T> extends Factory<T> { 24 | SignumKey newKey(long idA, long idB); 25 | } 26 | 27 | interface LinkKey3Factory<T> extends Factory<T> { 28 | SignumKey newKey(long idA, long idB, long idC); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/brs/db/Table.java: -------------------------------------------------------------------------------- 1 | package brs.db; 2 | 3 | public interface Table { 4 | /** 5 | * For future use; currently unused. 6 | */ 7 | void optimize(); 8 | } 9 | -------------------------------------------------------------------------------- /src/brs/db/TransactionDb.java: -------------------------------------------------------------------------------- 1 | package brs.db; 2 | 3 | import brs.SignumException; 4 | import brs.Transaction; 5 | import brs.schema.tables.records.TransactionRecord; 6 | 7 | import java.util.List; 8 | 9 | public interface TransactionDb extends Table { 10 | Transaction findTransaction(long transactionId); 11 | 12 | Transaction findTransactionByFullHash(String fullHash); // TODO add byte[] method 13 | 14 | boolean hasTransaction(long transactionId); 15 | 16 | boolean hasTransactionByFullHash(String fullHash); // TODO add byte[] method 17 | 18 | Transaction loadTransaction(TransactionRecord transactionRecord) throws SignumException.ValidationException; 19 | 20 | List<Transaction> findBlockTransactions(long blockId, boolean onlySigned); 21 | 22 | void saveTransactions(List<Transaction> transactions); 23 | } 24 | -------------------------------------------------------------------------------- /src/brs/db/ValuesTable.java: -------------------------------------------------------------------------------- 1 | package brs.db; 2 | 3 | import java.util.List; 4 | 5 | public interface ValuesTable<T, V> extends DerivedTable { 6 | List<V> get(SignumKey dbKey); 7 | 8 | void insert(T t, List<V> values); 9 | 10 | @Override 11 | void rollback(int height); 12 | 13 | @Override 14 | void truncate(); 15 | } 16 | -------------------------------------------------------------------------------- /src/brs/db/VersionedEntityTable.java: -------------------------------------------------------------------------------- 1 | package brs.db; 2 | 3 | public interface VersionedEntityTable<T> extends DerivedTable, EntityTable<T> { 4 | @Override 5 | void rollback(int height); 6 | 7 | boolean delete(T t); 8 | 9 | @Override 10 | void trim(int height); 11 | } 12 | -------------------------------------------------------------------------------- /src/brs/db/VersionedValuesTable.java: -------------------------------------------------------------------------------- 1 | package brs.db; 2 | 3 | public interface VersionedValuesTable<T, V> extends DerivedTable, ValuesTable<T, V> { 4 | @Override 5 | void rollback(int height); 6 | 7 | @Override 8 | void trim(int height); 9 | } 10 | -------------------------------------------------------------------------------- /src/brs/db/cache/TransactionExpiry.java: -------------------------------------------------------------------------------- 1 | package brs.db.cache; 2 | 3 | import brs.Transaction; 4 | import brs.util.Time; 5 | import org.ehcache.expiry.ExpiryPolicy; 6 | 7 | import java.time.Duration; 8 | import java.util.function.Supplier; 9 | 10 | class TransactionExpiry implements ExpiryPolicy<Long, Transaction> { 11 | 12 | private static final Time time = new Time.EpochTime(); 13 | 14 | @Override 15 | public Duration getExpiryForCreation(Long key, Transaction value) { 16 | return Duration.ofSeconds((long) value.getExpiration() - time.getTime()); 17 | } 18 | 19 | @Override 20 | public Duration getExpiryForAccess(Long key, Supplier<? extends Transaction> value) { 21 | return Duration.ofSeconds((long) value.get().getExpiration() - time.getTime()); 22 | } 23 | 24 | @Override 25 | public Duration getExpiryForUpdate(Long key, Supplier<? extends Transaction> oldValue, Transaction newValue) { 26 | return Duration.ofSeconds((long) newValue.getExpiration() - time.getTime()); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/brs/db/sql/DbUtils.java: -------------------------------------------------------------------------------- 1 | package brs.db.sql; 2 | 3 | import org.jooq.SelectQuery; 4 | 5 | public final class DbUtils { 6 | 7 | private DbUtils() { 8 | } // never 9 | 10 | public static void close(AutoCloseable... closeables) { 11 | for (AutoCloseable closeable : closeables) { 12 | if (closeable != null) { 13 | try { 14 | closeable.close(); 15 | } catch (Exception ignored) { 16 | } 17 | } 18 | } 19 | } 20 | 21 | public static void applyLimits(SelectQuery query, int from, int to ) { 22 | int limit = to >= 0 && to >= from && to < Integer.MAX_VALUE ? to - from + 1 : 0; 23 | if (limit > 0 && from > 0) { 24 | query.addLimit(from, limit); 25 | } 26 | else if (limit > 0) { 27 | query.addLimit(limit); 28 | } 29 | else if (from > 0) { 30 | query.addOffset(from); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/brs/db/sql/SqlDbs.java: -------------------------------------------------------------------------------- 1 | package brs.db.sql; 2 | 3 | import brs.db.BlockDb; 4 | import brs.db.PeerDb; 5 | import brs.db.TransactionDb; 6 | import brs.db.store.Dbs; 7 | 8 | public class SqlDbs implements Dbs { 9 | 10 | private final BlockDb blockDb; 11 | private final TransactionDb transactionDb; 12 | private final PeerDb peerDb; 13 | 14 | public SqlDbs() { 15 | this.blockDb = new SqlBlockDb(); 16 | this.transactionDb = new SqlTransactionDb(); 17 | this.peerDb = new SqlPeerDb(); 18 | } 19 | 20 | @Override 21 | public BlockDb getBlockDb() { 22 | return blockDb; 23 | } 24 | 25 | @Override 26 | public TransactionDb getTransactionDb() { 27 | return transactionDb; 28 | } 29 | 30 | @Override 31 | public PeerDb getPeerDb() { 32 | return peerDb; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/brs/db/sql/VersionedValuesSqlTable.java: -------------------------------------------------------------------------------- 1 | package brs.db.sql; 2 | 3 | import brs.db.VersionedValuesTable; 4 | import brs.db.store.DerivedTableManager; 5 | import org.jooq.impl.TableImpl; 6 | 7 | public abstract class VersionedValuesSqlTable<T, V> extends ValuesSqlTable<T, V> implements VersionedValuesTable<T, V> { 8 | VersionedValuesSqlTable(String table, TableImpl<?> tableClass, DbKey.Factory<T> dbKeyFactory, DerivedTableManager derivedTableManager) { 9 | super(table, tableClass, dbKeyFactory, true, derivedTableManager); 10 | } 11 | 12 | @Override 13 | public final void rollback(int height) { 14 | VersionedEntitySqlTable.rollback(table, tableClass, heightField, latestField, height, dbKeyFactory); 15 | } 16 | 17 | @Override 18 | public final void trim(int height) { 19 | VersionedEntitySqlTable.trim(tableClass, heightField, height, dbKeyFactory); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/brs/db/sql/dialects/DatabaseInstance.java: -------------------------------------------------------------------------------- 1 | package brs.db.sql.dialects; 2 | 3 | import com.zaxxer.hikari.HikariConfig; 4 | import com.zaxxer.hikari.HikariDataSource; 5 | import org.jooq.SQLDialect; 6 | 7 | 8 | 9 | public interface DatabaseInstance { 10 | enum SupportStatus { 11 | STABLE, 12 | DEPRECATED, 13 | EXPERIMENTAL 14 | } 15 | void onStartup(); 16 | void onShutdown(); 17 | HikariConfig getConfig(); 18 | HikariDataSource getDataSource(); 19 | String getMigrationSqlScriptPath(); 20 | String getMigrationClassPath(); 21 | String getDatabaseVersionSQLScript(); 22 | SQLDialect getDialect(); 23 | SupportStatus getSupportStatus(); 24 | } 25 | -------------------------------------------------------------------------------- /src/brs/db/sql/dialects/DatabaseInstanceFactory.java: -------------------------------------------------------------------------------- 1 | package brs.db.sql.dialects; 2 | 3 | 4 | import brs.props.PropertyService; 5 | import brs.props.Props; 6 | import org.jooq.SQLDialect; 7 | import org.jooq.tools.jdbc.JDBCUtils; 8 | 9 | public class DatabaseInstanceFactory { 10 | 11 | public static DatabaseInstance createInstance(PropertyService propertyService) { 12 | String dbUrl = propertyService.getString(Props.DB_URL); 13 | SQLDialect dialect = JDBCUtils.dialect(dbUrl); 14 | 15 | switch (dialect){ 16 | case H2: 17 | return new DatabaseInstanceH2(propertyService); 18 | case MARIADB: 19 | case MYSQL: 20 | return new DatabaseInstanceMariaDb(propertyService); 21 | case SQLITE: 22 | return new DatabaseInstanceSqlite(propertyService); 23 | case POSTGRES: 24 | return new DatabaseInstancePostgres(propertyService); 25 | default: 26 | throw new IllegalArgumentException("Database dialect not supported: " + dialect ); 27 | } 28 | 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/brs/db/sql/migration/V7_3__MigrateBalances.java: -------------------------------------------------------------------------------- 1 | package brs.db.sql.migration; 2 | 3 | import java.sql.Statement; 4 | 5 | import brs.db.sql.Db; 6 | import brs.props.Props; 7 | import org.flywaydb.core.api.migration.BaseJavaMigration; 8 | import org.flywaydb.core.api.migration.Context; 9 | import org.jooq.SQLDialect; 10 | import org.jooq.tools.jdbc.JDBCUtils; 11 | 12 | public class V7_3__MigrateBalances extends BaseJavaMigration { 13 | 14 | public void migrate(Context context) throws Exception { 15 | 16 | if (Db.getDialect() == SQLDialect.SQLITE || 17 | Db.getDialect() == SQLDialect.POSTGRES 18 | ) { 19 | return; 20 | } 21 | 22 | // copy all balance entries 23 | Statement selectTx = context.getConnection().createStatement(); 24 | selectTx.executeUpdate( 25 | "INSERT INTO account_balance(id, balance, unconfirmed_balance, forged_balance, height, latest) " + 26 | "SELECT id, balance, unconfirmed_balance, forged_balance, height, latest FROM account" 27 | ); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/brs/db/store/AliasStore.java: -------------------------------------------------------------------------------- 1 | package brs.db.store; 2 | 3 | import brs.Alias; 4 | import brs.db.SignumKey; 5 | import brs.db.VersionedEntityTable; 6 | 7 | import java.util.Collection; 8 | 9 | public interface AliasStore { 10 | SignumKey.LongKeyFactory<Alias> getAliasDbKeyFactory(); 11 | SignumKey.LongKeyFactory<Alias.Offer> getOfferDbKeyFactory(); 12 | 13 | VersionedEntityTable<Alias> getAliasTable(); 14 | 15 | VersionedEntityTable<Alias.Offer> getOfferTable(); 16 | 17 | Collection<Alias> getAliasesByOwner(long accountId, String name, Long tld, int from, int to); 18 | 19 | Collection<Alias> getTLDs(int from, int to); 20 | 21 | Collection<Alias.Offer> getAliasOffers(long account, long buyer, int from, int to); 22 | 23 | Alias getAlias(String aliasName, long tld); 24 | 25 | Alias getTLD(String tldName); 26 | 27 | Alias getTLD(long tldId); 28 | } 29 | -------------------------------------------------------------------------------- /src/brs/db/store/AssetStore.java: -------------------------------------------------------------------------------- 1 | package brs.db.store; 2 | 3 | import brs.Asset; 4 | import brs.db.SignumKey; 5 | import brs.db.sql.EntitySqlTable; 6 | 7 | import java.util.Collection; 8 | 9 | public interface AssetStore { 10 | SignumKey.LongKeyFactory<Asset> getAssetDbKeyFactory(); 11 | 12 | EntitySqlTable<Asset> getAssetTable(); 13 | 14 | Collection<Asset> getAssetsIssuedBy(long accountId, int from, int to); 15 | 16 | Asset getAsset(long assetId); 17 | 18 | Collection<Asset> getAssetsByName(String name, int from, int to); 19 | } 20 | -------------------------------------------------------------------------------- /src/brs/db/store/AssetTransferStore.java: -------------------------------------------------------------------------------- 1 | package brs.db.store; 2 | 3 | import brs.AssetTransfer; 4 | import brs.db.SignumKey; 5 | import brs.db.sql.EntitySqlTable; 6 | 7 | import java.util.Collection; 8 | 9 | public interface AssetTransferStore { 10 | SignumKey.LinkKeyFactory<AssetTransfer> getTransferDbKeyFactory(); 11 | 12 | EntitySqlTable<AssetTransfer> getAssetTransferTable(); 13 | 14 | Collection<AssetTransfer> getAssetTransfers(long assetId, int from, int to); 15 | 16 | Collection<AssetTransfer> getAccountAssetTransfers(long accountId, int from, int to); 17 | 18 | Collection<AssetTransfer> getAccountAssetTransfers(long accountId, long assetId, int from, int to); 19 | 20 | int getTransferCount(long assetId); 21 | } 22 | -------------------------------------------------------------------------------- /src/brs/db/store/Dbs.java: -------------------------------------------------------------------------------- 1 | package brs.db.store; 2 | 3 | import brs.db.BlockDb; 4 | import brs.db.PeerDb; 5 | import brs.db.TransactionDb; 6 | 7 | public interface Dbs { 8 | 9 | BlockDb getBlockDb(); 10 | 11 | TransactionDb getTransactionDb(); 12 | 13 | PeerDb getPeerDb(); 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/brs/db/store/DerivedTableManager.java: -------------------------------------------------------------------------------- 1 | package brs.db.store; 2 | 3 | import brs.db.DerivedTable; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | 7 | import java.util.List; 8 | import java.util.concurrent.CopyOnWriteArrayList; 9 | 10 | public class DerivedTableManager { 11 | 12 | private final Logger logger = LoggerFactory.getLogger(DerivedTableManager.class); 13 | 14 | private final List<DerivedTable> derivedTables = new CopyOnWriteArrayList<>(); 15 | 16 | public List<DerivedTable> getDerivedTables() { 17 | return derivedTables; 18 | } 19 | 20 | public void registerDerivedTable(DerivedTable table) { 21 | logger.info("Registering derived table " + table.getClass()); 22 | derivedTables.add(table); 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/brs/db/store/EscrowStore.java: -------------------------------------------------------------------------------- 1 | package brs.db.store; 2 | 3 | import brs.Escrow; 4 | import brs.Transaction; 5 | import brs.db.SignumKey; 6 | import brs.db.VersionedEntityTable; 7 | import brs.db.sql.DbKey; 8 | 9 | import java.util.Collection; 10 | import java.util.List; 11 | 12 | public interface EscrowStore { 13 | 14 | SignumKey.LongKeyFactory<Escrow> getEscrowDbKeyFactory(); 15 | 16 | VersionedEntityTable<Escrow> getEscrowTable(); 17 | 18 | DbKey.LinkKeyFactory<Escrow.Decision> getDecisionDbKeyFactory(); 19 | 20 | VersionedEntityTable<Escrow.Decision> getDecisionTable(); 21 | 22 | Collection<Escrow> getEscrowTransactionsByParticipant(Long accountId); 23 | 24 | List<Transaction> getResultTransactions(); 25 | 26 | Collection<Escrow.Decision> getDecisions(Long id); 27 | } 28 | -------------------------------------------------------------------------------- /src/brs/db/store/IndirectIncomingStore.java: -------------------------------------------------------------------------------- 1 | package brs.db.store; 2 | 3 | import java.util.Collection; 4 | 5 | import brs.IndirectIncoming; 6 | 7 | public interface IndirectIncomingStore { 8 | void addIndirectIncomings(Collection<IndirectIncoming> indirectIncomings); 9 | 10 | Collection<Long> getIndirectIncomings(long accountId, int from, int to); 11 | 12 | public IndirectIncoming getIndirectIncoming(long accountId, long transactionId); 13 | 14 | public void rollback(int height); 15 | } 16 | -------------------------------------------------------------------------------- /src/brs/db/store/SubscriptionStore.java: -------------------------------------------------------------------------------- 1 | package brs.db.store; 2 | 3 | import brs.Subscription; 4 | import brs.db.SignumKey; 5 | import brs.db.VersionedEntityTable; 6 | 7 | import java.util.Collection; 8 | 9 | public interface SubscriptionStore { 10 | 11 | SignumKey.LongKeyFactory<Subscription> getSubscriptionDbKeyFactory(); 12 | 13 | VersionedEntityTable<Subscription> getSubscriptionTable(); 14 | 15 | void saveSubscriptions(Collection<Subscription> subscriptions); 16 | 17 | Collection<Subscription> getSubscriptionsByParticipant(Long accountId); 18 | 19 | Collection<Subscription> getIdSubscriptions(Long accountId); 20 | 21 | Collection<Subscription> getSubscriptionsToId(Long accountId); 22 | 23 | Collection<Subscription> getUpdateSubscriptions(int timestamp); 24 | } 25 | -------------------------------------------------------------------------------- /src/brs/db/store/TradeStore.java: -------------------------------------------------------------------------------- 1 | package brs.db.store; 2 | 3 | import brs.Trade; 4 | import brs.db.SignumKey; 5 | import brs.db.sql.EntitySqlTable; 6 | 7 | import java.util.Collection; 8 | 9 | public interface TradeStore { 10 | Collection<Trade> getAllTrades(int from, int to); 11 | 12 | Collection<Trade> getAssetTrades(long assetId, int from, int to); 13 | 14 | Collection<Trade> getAccountTrades(long accountId, int from, int to); 15 | 16 | Collection<Trade> getAccountAssetTrades(long accountId, long assetId, int from, int to); 17 | 18 | Collection<Trade> getOrderTrades(long orderId); 19 | 20 | long getTradeVolume(long assetId, int heightStart, int heightEnd); 21 | 22 | long getHighPrice(long assetId, int heightStart, int heightEnd) 23 | ; 24 | long getLowPrice(long assetId, int heightStart, int heightEnd); 25 | 26 | long getOpenPrice(long assetId, int heightStart, int heightEnd); 27 | 28 | long getClosePrice(long assetId, int heightStart, int heightEnd); 29 | 30 | int getTradeCount(long assetId); 31 | 32 | SignumKey.LinkKeyFactory<Trade> getTradeDbKeyFactory(); 33 | 34 | EntitySqlTable<Trade> getTradeTable(); 35 | } 36 | -------------------------------------------------------------------------------- /src/brs/db/store/TransactionProcessorStore.java: -------------------------------------------------------------------------------- 1 | package brs.db.store; 2 | 3 | import brs.Transaction; 4 | import brs.db.SignumKey; 5 | import brs.db.sql.EntitySqlTable; 6 | 7 | import java.util.Collection; 8 | import java.util.Map; 9 | import java.util.Set; 10 | 11 | public interface TransactionProcessorStore { 12 | // WATCH: BUSINESS-LOGIC 13 | void processLater(Collection<Transaction> transactions); 14 | 15 | SignumKey.LongKeyFactory<Transaction> getUnconfirmedTransactionDbKeyFactory(); 16 | 17 | Set<Transaction> getLostTransactions(); 18 | 19 | Map<Long, Integer> getLostTransactionHeights(); 20 | 21 | EntitySqlTable<Transaction> getUnconfirmedTransactionTable(); 22 | 23 | int deleteTransaction (Transaction transaction); 24 | 25 | boolean hasTransaction(long transactionId); 26 | } 27 | -------------------------------------------------------------------------------- /src/brs/feesuggestions/FeeSuggestion.java: -------------------------------------------------------------------------------- 1 | package brs.feesuggestions; 2 | 3 | public class FeeSuggestion { 4 | 5 | private final long cheapFee; 6 | private final long standardFee; 7 | private final long priorityFee; 8 | 9 | public FeeSuggestion(long cheapFee, long standardFee, long priorityFee) { 10 | this.cheapFee = cheapFee; 11 | this.standardFee = standardFee; 12 | this.priorityFee = priorityFee; 13 | } 14 | 15 | public long getCheapFee() { 16 | return cheapFee; 17 | } 18 | 19 | public long getStandardFee() { 20 | return standardFee; 21 | } 22 | 23 | public long getPriorityFee() { 24 | return priorityFee; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/brs/feesuggestions/FeeSuggestionType.java: -------------------------------------------------------------------------------- 1 | package brs.feesuggestions; 2 | 3 | import java.util.Arrays; 4 | 5 | public enum FeeSuggestionType { 6 | CHEAP("cheap"), STANDARD("standard"), PRIORITY("priority"); 7 | 8 | private final String type; 9 | 10 | FeeSuggestionType(String type) { 11 | this.type = type; 12 | } 13 | 14 | public String getType() { 15 | return type; 16 | } 17 | 18 | public static FeeSuggestionType getByType(String type) { 19 | return Arrays.stream(values()).filter(s -> s.type.equals(type)).findFirst().orElse(null); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/brs/fluxcapacitor/FluxEnable.java: -------------------------------------------------------------------------------- 1 | package brs.fluxcapacitor; 2 | 3 | /** 4 | * A special type of FluxValue used for eg. forks that goes from disabled 5 | * to enabled at a certain historical moment. 6 | */ 7 | public class FluxEnable extends FluxValue<Boolean> { 8 | private final HistoricalMoments enablePoint; 9 | 10 | /** 11 | * Create a FluxEnable value. 12 | * 13 | * @param enablePoint The historical moment at which this FluxEnable takes 14 | * effect 15 | */ 16 | public FluxEnable(HistoricalMoments enablePoint) { 17 | super(false, new ValueChange<>(enablePoint, true)); 18 | this.enablePoint = enablePoint; 19 | } 20 | 21 | /** 22 | * Returns the moment this FluxEnable takes effect. 23 | * 24 | * @return an {@link HistoricalMoments} 25 | */ 26 | public HistoricalMoments getEnablePoint() { 27 | return enablePoint; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/brs/peer/AddPeers.java: -------------------------------------------------------------------------------- 1 | package brs.peer; 2 | 3 | import brs.util.JSON; 4 | import com.google.gson.JsonArray; 5 | import com.google.gson.JsonElement; 6 | import com.google.gson.JsonObject; 7 | 8 | final class AddPeers implements PeerServlet.PeerRequestHandler { 9 | 10 | static final AddPeers instance = new AddPeers(); 11 | 12 | private AddPeers() { 13 | } 14 | 15 | @Override 16 | public JsonElement processRequest(JsonObject request, Peer peer) { 17 | JsonArray peers = JSON.getAsJsonArray(request.get("peers")); 18 | if (peers != null && Peers.getMorePeers) { 19 | for (JsonElement announcedAddress : peers) { 20 | Peers.addPeer(JSON.getAsString(announcedAddress)); 21 | } 22 | } 23 | return JSON.emptyJSON; 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/brs/peer/GetCumulativeDifficulty.java: -------------------------------------------------------------------------------- 1 | package brs.peer; 2 | 3 | import brs.Block; 4 | import brs.Blockchain; 5 | import com.google.gson.JsonElement; 6 | import com.google.gson.JsonObject; 7 | 8 | final class GetCumulativeDifficulty implements PeerServlet.PeerRequestHandler { 9 | 10 | private final Blockchain blockchain; 11 | 12 | GetCumulativeDifficulty(Blockchain blockchain) { 13 | this.blockchain = blockchain; 14 | } 15 | 16 | 17 | @Override 18 | public JsonElement processRequest(JsonObject request, Peer peer) { 19 | JsonObject response = new JsonObject(); 20 | 21 | Block lastBlock = blockchain.getLastBlock(); 22 | response.addProperty("cumulativeDifficulty", lastBlock.getCumulativeDifficulty().toString()); 23 | response.addProperty("blockchainHeight", lastBlock.getHeight()); 24 | return response; 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/brs/peer/GetNextBlockIds.java: -------------------------------------------------------------------------------- 1 | package brs.peer; 2 | 3 | import brs.Blockchain; 4 | import brs.util.Convert; 5 | import brs.util.JSON; 6 | import com.google.gson.JsonArray; 7 | import com.google.gson.JsonElement; 8 | import com.google.gson.JsonObject; 9 | 10 | import java.util.Collection; 11 | 12 | final class GetNextBlockIds implements PeerServlet.PeerRequestHandler { 13 | 14 | private final Blockchain blockchain; 15 | 16 | GetNextBlockIds(Blockchain blockchain) { 17 | this.blockchain = blockchain; 18 | } 19 | 20 | 21 | @Override 22 | public JsonElement processRequest(JsonObject request, Peer peer) { 23 | 24 | JsonObject response = new JsonObject(); 25 | 26 | JsonArray nextBlockIds = new JsonArray(); 27 | long blockId = Convert.parseUnsignedLong(JSON.getAsString(request.get("blockId"))); 28 | Collection<Long> ids = blockchain.getBlockIdsAfter(blockId, 100); 29 | 30 | for (Long id : ids) { 31 | nextBlockIds.add(Convert.toUnsignedLong(id)); 32 | } 33 | 34 | response.add("nextBlockIds", nextBlockIds); 35 | 36 | return response; 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/brs/peer/GetPeers.java: -------------------------------------------------------------------------------- 1 | package brs.peer; 2 | 3 | import com.google.gson.JsonArray; 4 | import com.google.gson.JsonElement; 5 | import com.google.gson.JsonObject; 6 | 7 | final class GetPeers implements PeerServlet.PeerRequestHandler { 8 | 9 | static final GetPeers instance = new GetPeers(); 10 | 11 | private GetPeers() { 12 | } 13 | 14 | @Override 15 | public JsonElement processRequest(JsonObject request, Peer peer) { 16 | 17 | JsonObject response = new JsonObject(); 18 | 19 | JsonArray peers = new JsonArray(); 20 | for (Peer otherPeer : Peers.getAllPeers()) { 21 | 22 | if (!otherPeer.isBlacklisted() && otherPeer.getAnnouncedAddress() != null 23 | && otherPeer.getState() == Peer.State.CONNECTED && otherPeer.shareAddress()) { 24 | 25 | peers.add(otherPeer.getAnnouncedAddress()); 26 | 27 | } 28 | 29 | } 30 | response.add("peers", peers); 31 | 32 | return response; 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/brs/peer/ProcessTransactions.java: -------------------------------------------------------------------------------- 1 | package brs.peer; 2 | 3 | import brs.SignumException; 4 | import brs.TransactionProcessor; 5 | import brs.util.JSON; 6 | import com.google.gson.JsonElement; 7 | import com.google.gson.JsonObject; 8 | 9 | final class ProcessTransactions implements PeerServlet.PeerRequestHandler { 10 | 11 | private final TransactionProcessor transactionProcessor; 12 | 13 | ProcessTransactions(TransactionProcessor transactionProcessor) { 14 | this.transactionProcessor = transactionProcessor; 15 | } 16 | 17 | 18 | @Override 19 | public JsonElement processRequest(JsonObject request, Peer peer) { 20 | 21 | try { 22 | transactionProcessor.processPeerTransactions(request, peer); 23 | return JSON.emptyJSON; 24 | } catch (RuntimeException | SignumException.ValidationException e) { 25 | peer.blacklist(e, "received invalid data via requestType=processTransactions"); 26 | JsonObject response = new JsonObject(); 27 | response.addProperty("error", e.toString()); 28 | return response; 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/brs/props/CaselessProperties.java: -------------------------------------------------------------------------------- 1 | package brs.props; 2 | 3 | import java.util.Properties; 4 | 5 | /** 6 | * Overrides {@link java.util.Properties} to make all the keys lowercase, 7 | * thus making the config file keys case-insensitve. 8 | * Courtesy Jim Yingst 9 | * https://coderanch.com/t/277128/java/Properties-ignoring-case 10 | */ 11 | public class CaselessProperties extends Properties { 12 | public CaselessProperties() { 13 | super(); 14 | } 15 | 16 | public CaselessProperties(CaselessProperties properties) { 17 | super(properties); 18 | } 19 | 20 | public Object put(Object key, Object value) { 21 | String lowercase = ((String) key).toLowerCase(); 22 | return super.put(lowercase, value); 23 | } 24 | 25 | public String getProperty(String key) { 26 | String lowercase = key.toLowerCase(); 27 | return super.getProperty(lowercase); 28 | } 29 | 30 | public String getProperty(String key, String defaultValue) { 31 | String lowercase = key.toLowerCase(); 32 | return super.getProperty(lowercase, defaultValue); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/brs/props/Prop.java: -------------------------------------------------------------------------------- 1 | package brs.props; 2 | 3 | //TODO: Create JavaDocs and remove this 4 | @SuppressWarnings({ "checkstyle:MissingJavadocTypeCheck", "checkstyle:MissingJavadocMethodCheck" }) 5 | 6 | public class Prop<T> { 7 | 8 | final String name; 9 | final T defaultValue; 10 | 11 | public Prop(String name, T defaultValue) { 12 | this.name = name; 13 | this.defaultValue = defaultValue; 14 | } 15 | 16 | public String getName() { 17 | return name; 18 | } 19 | 20 | public T getDefaultValue() { 21 | return defaultValue; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/brs/props/PropertyService.java: -------------------------------------------------------------------------------- 1 | package brs.props; 2 | 3 | import java.util.List; 4 | 5 | import signum.net.NetworkParameters; 6 | 7 | public interface PropertyService { 8 | 9 | Boolean getBoolean(String propName, boolean assume); 10 | 11 | Boolean getBoolean(Prop<Boolean> prop); 12 | 13 | int getInt(Prop<Integer> prop); 14 | 15 | String getString(Prop<String> name); 16 | 17 | List<String> getStringList(Prop<String> name); 18 | 19 | void setNetworkParameters(NetworkParameters params); 20 | } 21 | -------------------------------------------------------------------------------- /src/brs/schema/DefaultCatalog.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is generated by jOOQ. 3 | */ 4 | package brs.schema; 5 | 6 | 7 | import java.util.Arrays; 8 | import java.util.List; 9 | 10 | import org.jooq.Schema; 11 | import org.jooq.impl.CatalogImpl; 12 | 13 | 14 | /** 15 | * This class is generated by jOOQ. 16 | */ 17 | @SuppressWarnings({ "all", "unchecked", "rawtypes" }) 18 | public class DefaultCatalog extends CatalogImpl { 19 | 20 | private static final long serialVersionUID = 1L; 21 | 22 | /** 23 | * The reference instance of <code>DEFAULT_CATALOG</code> 24 | */ 25 | public static final DefaultCatalog DEFAULT_CATALOG = new DefaultCatalog(); 26 | 27 | /** 28 | * The schema <code>DB</code>. 29 | */ 30 | public final Db DB = Db.DB; 31 | 32 | /** 33 | * No further instances allowed 34 | */ 35 | private DefaultCatalog() { 36 | super(""); 37 | } 38 | 39 | @Override 40 | public final List<Schema> getSchemas() { 41 | return Arrays.asList( 42 | Db.DB 43 | ); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/brs/services/ATService.java: -------------------------------------------------------------------------------- 1 | package brs.services; 2 | 3 | import brs.at.AT; 4 | import brs.util.CollectionWithIndex; 5 | 6 | import java.util.Collection; 7 | 8 | public interface ATService { 9 | 10 | Collection<Long> getAllATIds(Long codeHashId); 11 | 12 | CollectionWithIndex<Long> getATsIssuedBy(Long accountId, Long codeHashId, int from, int to); 13 | 14 | AT getAT(Long atId); 15 | 16 | AT getAT(Long atId, int height); 17 | } 18 | -------------------------------------------------------------------------------- /src/brs/services/BlockService.java: -------------------------------------------------------------------------------- 1 | package brs.services; 2 | 3 | import brs.Block; 4 | import brs.BlockchainProcessor; 5 | import brs.BlockchainProcessor.BlockNotAcceptedException; 6 | import brs.BlockchainProcessor.BlockOutOfOrderException; 7 | 8 | public interface BlockService { 9 | 10 | void preVerify(Block block, Block prevBlock) throws BlockchainProcessor.BlockNotAcceptedException, InterruptedException; 11 | 12 | void preVerify(Block block, Block prevBlock, byte[] scoopData) throws BlockchainProcessor.BlockNotAcceptedException, InterruptedException; 13 | 14 | void watchBlock(Block block); 15 | 16 | long getBlockReward(Block block); 17 | 18 | void calculateBaseTarget(Block block, Block lastBlock) throws BlockOutOfOrderException; 19 | 20 | void setPrevious(Block block, Block previousBlock); 21 | 22 | boolean verifyGenerationSignature(Block block) throws BlockNotAcceptedException; 23 | 24 | boolean verifyBlockSignature(Block block) throws BlockOutOfOrderException; 25 | 26 | void apply(Block block); 27 | 28 | int getScoopNum(Block block); 29 | } 30 | -------------------------------------------------------------------------------- /src/brs/services/IndirectIncomingService.java: -------------------------------------------------------------------------------- 1 | package brs.services; 2 | 3 | import brs.Transaction; 4 | 5 | public interface IndirectIncomingService { 6 | void processTransaction(Transaction transaction); 7 | boolean isIndirectlyReceiving(Transaction transaction, long accountId); 8 | public void rollback(int height); 9 | } 10 | -------------------------------------------------------------------------------- /src/brs/services/SubscriptionService.java: -------------------------------------------------------------------------------- 1 | package brs.services; 2 | 3 | import brs.Account; 4 | import brs.Block; 5 | import brs.Subscription; 6 | 7 | import java.util.Collection; 8 | 9 | public interface SubscriptionService { 10 | 11 | Subscription getSubscription(Long id); 12 | 13 | Collection<Subscription> getSubscriptionsByParticipant(Long accountId); 14 | 15 | Collection<Subscription> getSubscriptionsToId(Long accountId); 16 | 17 | void addSubscription(Account sender, long recipientId, Long id, Long amountNQT, int startTimestamp, int frequency); 18 | 19 | boolean isEnabled(); 20 | 21 | void applyConfirmed(Block block, int blockchainHeight); 22 | 23 | void removeSubscription(Long id); 24 | 25 | long calculateFees(int timestamp, int height); 26 | 27 | void clearRemovals(); 28 | 29 | void addRemoval(Long id); 30 | 31 | long applyUnconfirmed(int timestamp, int blockchainHeight); 32 | } 33 | -------------------------------------------------------------------------------- /src/brs/services/TimeService.java: -------------------------------------------------------------------------------- 1 | package brs.services; 2 | 3 | import brs.util.Time.FasterTime; 4 | 5 | public interface TimeService { 6 | 7 | int getEpochTime(); 8 | 9 | long getEpochTimeMillis(); 10 | 11 | void setTime(FasterTime fasterTime); 12 | } 13 | -------------------------------------------------------------------------------- /src/brs/services/TransactionService.java: -------------------------------------------------------------------------------- 1 | package brs.services; 2 | 3 | import brs.SignumException; 4 | import brs.Transaction; 5 | 6 | public interface TransactionService { 7 | 8 | boolean verifyPublicKey(Transaction transaction); 9 | 10 | void validate(Transaction transaction) throws SignumException.ValidationException; 11 | 12 | void startNewBlock(); 13 | 14 | boolean applyUnconfirmed(Transaction transaction); 15 | 16 | void apply(Transaction transaction); 17 | 18 | void undoUnconfirmed(Transaction transaction); 19 | } 20 | -------------------------------------------------------------------------------- /src/brs/services/impl/ATServiceImpl.java: -------------------------------------------------------------------------------- 1 | package brs.services.impl; 2 | 3 | import brs.at.AT; 4 | import brs.db.store.ATStore; 5 | import brs.services.ATService; 6 | import brs.util.CollectionWithIndex; 7 | 8 | import java.util.Collection; 9 | 10 | public class ATServiceImpl implements ATService { 11 | 12 | private final ATStore atStore; 13 | 14 | public ATServiceImpl(ATStore atStore) { 15 | this.atStore = atStore; 16 | } 17 | 18 | @Override 19 | public Collection<Long> getAllATIds(Long codeHashId) { 20 | return atStore.getAllATIds(codeHashId); 21 | } 22 | 23 | @Override 24 | public CollectionWithIndex<Long> getATsIssuedBy(Long accountId, Long codeHashId, int from, int to) { 25 | return new CollectionWithIndex<Long>(atStore.getATsIssuedBy(accountId, codeHashId, from, to), from, to); 26 | } 27 | 28 | @Override 29 | public AT getAT(Long id, int height) { 30 | return atStore.getAT(id, height); 31 | } 32 | 33 | @Override 34 | public AT getAT(Long id) { 35 | return atStore.getAT(id); 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/brs/services/impl/TimeServiceImpl.java: -------------------------------------------------------------------------------- 1 | package brs.services.impl; 2 | 3 | import brs.services.TimeService; 4 | import brs.util.Time; 5 | import brs.util.Time.FasterTime; 6 | 7 | import java.util.concurrent.atomic.AtomicReference; 8 | 9 | public class TimeServiceImpl implements TimeService { 10 | 11 | private static final AtomicReference<Time> time = new AtomicReference<>(new Time.EpochTime()); 12 | 13 | @Override 14 | public int getEpochTime() { 15 | return time.get().getTime(); 16 | } 17 | 18 | @Override 19 | public long getEpochTimeMillis() { 20 | return time.get().getTimeInMillis(); 21 | } 22 | 23 | @Override 24 | public void setTime(FasterTime t) { 25 | time.set(t); 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/brs/transactionduplicates/TransactionDuplicationKey.java: -------------------------------------------------------------------------------- 1 | package brs.transactionduplicates; 2 | 3 | import brs.TransactionType; 4 | 5 | public class TransactionDuplicationKey { 6 | 7 | final TransactionType transactionType; 8 | 9 | final String key; 10 | 11 | public static final TransactionDuplicationKey IS_ALWAYS_DUPLICATE = new TransactionDuplicationKey(null, "always"); 12 | 13 | public static final TransactionDuplicationKey IS_NEVER_DUPLICATE = new TransactionDuplicationKey(null, "never"); 14 | 15 | public TransactionDuplicationKey(TransactionType transactionType, String key) { 16 | this.transactionType = transactionType; 17 | this.key = key; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/brs/transactionduplicates/TransactionDuplicationResult.java: -------------------------------------------------------------------------------- 1 | package brs.transactionduplicates; 2 | 3 | import brs.Transaction; 4 | 5 | public class TransactionDuplicationResult { 6 | 7 | final boolean duplicate; 8 | 9 | final Transaction transaction; 10 | 11 | public TransactionDuplicationResult(boolean duplicate, Transaction transaction) { 12 | this.duplicate = duplicate; 13 | this.transaction = transaction; 14 | } 15 | 16 | public boolean isDuplicate() { 17 | return duplicate; 18 | } 19 | 20 | public Transaction getTransaction() { 21 | return transaction; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/brs/unconfirmedtransactions/UnconfirmedTransactionStore.java: -------------------------------------------------------------------------------- 1 | package brs.unconfirmedtransactions; 2 | 3 | import brs.SignumException; 4 | import brs.Transaction; 5 | import brs.peer.Peer; 6 | 7 | import java.util.List; 8 | 9 | public interface UnconfirmedTransactionStore { 10 | 11 | boolean put(Transaction transaction, Peer peer) throws SignumException.ValidationException; 12 | 13 | Transaction get(Long transactionId); 14 | 15 | boolean exists(Long transactionId); 16 | 17 | long getFreeSlot(int numberOfBlocks); 18 | 19 | List<Transaction> getAll(); 20 | 21 | List<Transaction> getAllFor(Peer peer); 22 | 23 | void remove(Transaction transaction); 24 | 25 | void clear(); 26 | 27 | void resetAccountBalances(); 28 | 29 | void markFingerPrintsOf(Peer peer, List<Transaction> transactions); 30 | 31 | void removeForgedTransactions(List<Transaction> transactions); 32 | 33 | int getAmount(); 34 | } 35 | -------------------------------------------------------------------------------- /src/brs/unconfirmedtransactions/UnconfirmedTransactionTiming.java: -------------------------------------------------------------------------------- 1 | package brs.unconfirmedtransactions; 2 | 3 | import brs.Transaction; 4 | 5 | class UnconfirmedTransactionTiming { 6 | 7 | private final Transaction transaction; 8 | private final long timestamp; 9 | 10 | public UnconfirmedTransactionTiming(Transaction transaction, long timestamp) { 11 | this.transaction = transaction; 12 | this.timestamp = timestamp; 13 | } 14 | 15 | public Transaction getTransaction() { 16 | return transaction; 17 | } 18 | 19 | public long getTimestamp() { 20 | return timestamp; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/brs/util/CountingInputStream.java: -------------------------------------------------------------------------------- 1 | package brs.util; 2 | 3 | import java.io.FilterInputStream; 4 | import java.io.IOException; 5 | import java.io.InputStream; 6 | 7 | public class CountingInputStream extends FilterInputStream { 8 | 9 | private long count; 10 | 11 | public CountingInputStream(InputStream in) { 12 | super(in); 13 | } 14 | 15 | @Override 16 | public int read() throws IOException { 17 | int read = super.read(); 18 | if (read >= 0) { 19 | count += 1; 20 | } 21 | return read; 22 | } 23 | 24 | @Override 25 | public int read(byte[] b, int off, int len) throws IOException { 26 | int read = super.read(b, off, len); 27 | if (read >= 0) { 28 | count += read; 29 | } 30 | return read; 31 | } 32 | 33 | @Override 34 | public long skip(long n) throws IOException { 35 | long skipped = super.skip(n); 36 | if (skipped >= 0) { 37 | count += skipped; 38 | } 39 | return skipped; 40 | } 41 | 42 | public long getCount() { 43 | return count; 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /src/brs/util/CountingOutputStream.java: -------------------------------------------------------------------------------- 1 | package brs.util; 2 | 3 | import java.io.FilterOutputStream; 4 | import java.io.IOException; 5 | import java.io.OutputStream; 6 | 7 | public class CountingOutputStream extends FilterOutputStream { 8 | 9 | private long count; 10 | 11 | public CountingOutputStream(OutputStream out) { 12 | super(out); 13 | } 14 | 15 | @Override 16 | public void write(int b) throws IOException { 17 | count += 1; 18 | super.write(b); 19 | } 20 | 21 | @Override 22 | public void write(byte[] b) throws IOException { 23 | count += b.length; 24 | super.write(b); 25 | } 26 | 27 | @Override 28 | public void write(byte[] b, int off, int len) throws IOException { 29 | count += len; 30 | super.write(b, off, len); 31 | } 32 | 33 | public long getCount() { 34 | return count; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/brs/util/Listener.java: -------------------------------------------------------------------------------- 1 | package brs.util; 2 | 3 | public interface Listener<T> { 4 | void notify(T t); 5 | 6 | } 7 | -------------------------------------------------------------------------------- /src/brs/util/Observable.java: -------------------------------------------------------------------------------- 1 | package brs.util; 2 | 3 | public interface Observable<T,E extends Enum<E>> { 4 | 5 | boolean addListener(Listener<T> listener, E eventType); 6 | 7 | boolean removeListener(Listener<T> listener, E eventType); 8 | 9 | } 10 | -------------------------------------------------------------------------------- /src/brs/util/StampedLockUtils.java: -------------------------------------------------------------------------------- 1 | package brs.util; 2 | 3 | import java.util.concurrent.locks.StampedLock; 4 | import java.util.function.Supplier; 5 | 6 | public class StampedLockUtils { 7 | public static <T> T stampedLockRead(StampedLock lock, Supplier<T> supplier) { 8 | long stamp = lock.tryOptimisticRead(); 9 | T retVal = supplier.get(); 10 | if (!lock.validate(stamp)) { 11 | stamp = lock.readLock(); 12 | try { 13 | retVal = supplier.get(); 14 | } finally { 15 | lock.unlockRead(stamp); 16 | } 17 | } 18 | return retVal; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/brs/util/StringUtils.java: -------------------------------------------------------------------------------- 1 | package brs.util; 2 | 3 | public class StringUtils { 4 | private StringUtils() { 5 | } 6 | 7 | public static boolean isEmpty(String str) { 8 | return str == null || str.length() == 0; 9 | } 10 | 11 | public static int countMatches(String str, String sub) { 12 | if (!isEmpty(str) && !isEmpty(sub)) { 13 | int count = 0; 14 | 15 | for(int idx = 0; (idx = str.indexOf(sub, idx)) != -1; idx += sub.length()) { 16 | ++count; 17 | } 18 | 19 | return count; 20 | } else { 21 | return 0; 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/brs/util/TextUtils.java: -------------------------------------------------------------------------------- 1 | package brs.util; 2 | 3 | import brs.Constants; 4 | 5 | import java.util.Locale; 6 | 7 | public class TextUtils { 8 | public TextUtils() { 9 | } 10 | 11 | private static boolean isInAlphabet(String input, String alphabet) { 12 | if (input == null) return true; 13 | for (char c : input.toLowerCase(Locale.ENGLISH).toCharArray()) { 14 | if (!alphabet.contains(String.valueOf(c))) return false; 15 | } 16 | return true; 17 | } 18 | 19 | public static boolean isInAlphabet(String input) { 20 | return isInAlphabet(input, Constants.ALPHABET); 21 | } 22 | 23 | public static boolean isInAlphabetOrUnderline(String input) { 24 | return isInAlphabet(input, Constants.ALPHABET_); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/brs/web/api/http/common/APITransactionManager.java: -------------------------------------------------------------------------------- 1 | package brs.web.api.http.common; 2 | 3 | import brs.Account; 4 | import brs.Attachment; 5 | import brs.SignumException; 6 | import com.google.gson.JsonElement; 7 | 8 | import javax.servlet.http.HttpServletRequest; 9 | 10 | public interface APITransactionManager { 11 | 12 | JsonElement createTransaction(HttpServletRequest req, Account senderAccount, Long recipientId, long amountNQT, Attachment attachment, long minimumFeeNQT) throws SignumException; 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/brs/web/api/http/common/LegacyDocTag.java: -------------------------------------------------------------------------------- 1 | package brs.web.api.http.common; 2 | 3 | public enum LegacyDocTag { 4 | 5 | ACCOUNTS("Accounts"), ALIASES("Aliases"), AE("Asset Exchange"), CREATE_TRANSACTION("Create Transaction"), 6 | BLOCKS("Blocks"), DGS("Digital Goods Store"), INFO("Server Info"), MESSAGES("Messages"), 7 | MINING("Mining"), TRANSACTIONS("Transactions"), TOKENS("Tokens"), VS("Voting System"), AT("Automated Transaction"), 8 | FEES("Fees"), UTILS("Utils"), ADMIN("Administrator"), PEER_INFO("Server Peer Info"); 9 | 10 | private final String displayName; 11 | 12 | LegacyDocTag(String displayName) { 13 | this.displayName = displayName; 14 | } 15 | 16 | public String getDisplayName() { 17 | return displayName; 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/brs/web/api/http/common/ParameterException.java: -------------------------------------------------------------------------------- 1 | package brs.web.api.http.common; 2 | 3 | import brs.SignumException; 4 | import com.google.gson.JsonElement; 5 | 6 | public final class ParameterException extends SignumException { 7 | 8 | private transient final JsonElement errorResponse; 9 | 10 | public ParameterException(JsonElement errorResponse) { 11 | this.errorResponse = errorResponse; 12 | } 13 | 14 | public JsonElement getErrorResponse() { 15 | return errorResponse; 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/brs/web/api/http/handler/AbstractGetUnconfirmedTransactions.java: -------------------------------------------------------------------------------- 1 | package brs.web.api.http.handler; 2 | 3 | import brs.web.api.http.ApiServlet; 4 | import brs.web.api.http.common.LegacyDocTag; 5 | 6 | abstract class AbstractGetUnconfirmedTransactions extends ApiServlet.JsonRequestHandler { 7 | 8 | AbstractGetUnconfirmedTransactions(LegacyDocTag[] legacyDocTags, String... parameters) { 9 | super(legacyDocTags, parameters); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/brs/web/api/http/handler/GetATDetails.java: -------------------------------------------------------------------------------- 1 | package brs.web.api.http.handler; 2 | 3 | import brs.SignumException; 4 | import brs.services.ParameterService; 5 | import brs.web.api.http.ApiServlet; 6 | import brs.web.api.http.common.JSONData; 7 | import brs.web.api.http.common.LegacyDocTag; 8 | import com.google.gson.JsonElement; 9 | 10 | import javax.servlet.http.HttpServletRequest; 11 | 12 | import static brs.web.api.http.common.Parameters.AT_PARAMETER; 13 | import static brs.web.api.http.common.Parameters.HEIGHT_PARAMETER; 14 | 15 | public class GetATDetails extends ApiServlet.JsonRequestHandler { 16 | 17 | private final ParameterService parameterService; 18 | 19 | public GetATDetails(ParameterService parameterService) { 20 | super(new LegacyDocTag[] {LegacyDocTag.AT}, AT_PARAMETER, HEIGHT_PARAMETER); 21 | this.parameterService = parameterService; 22 | } 23 | 24 | @Override 25 | protected 26 | JsonElement processRequest(HttpServletRequest req) throws SignumException { 27 | return JSONData.at(parameterService.getAT(req)); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/brs/web/api/http/handler/GetBalance.java: -------------------------------------------------------------------------------- 1 | package brs.web.api.http.handler; 2 | 3 | import brs.SignumException; 4 | import brs.web.api.http.common.LegacyDocTag; 5 | import brs.web.api.http.common.Parameters; 6 | import brs.services.ParameterService; 7 | import brs.web.api.http.ApiServlet; 8 | import brs.web.api.http.common.JSONData; 9 | import com.google.gson.JsonElement; 10 | 11 | import javax.servlet.http.HttpServletRequest; 12 | 13 | public final class GetBalance extends ApiServlet.JsonRequestHandler { 14 | 15 | private final ParameterService parameterService; 16 | 17 | public GetBalance(ParameterService parameterService) { 18 | super(new LegacyDocTag[]{LegacyDocTag.ACCOUNTS}, Parameters.ACCOUNT_PARAMETER); 19 | this.parameterService = parameterService; 20 | } 21 | 22 | @Override 23 | protected 24 | JsonElement processRequest(HttpServletRequest req) throws SignumException { 25 | return JSONData.accountBalance(parameterService.getAccount(req)); 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/brs/web/api/http/handler/GetDGSGood.java: -------------------------------------------------------------------------------- 1 | package brs.web.api.http.handler; 2 | 3 | import brs.SignumException; 4 | import brs.services.ParameterService; 5 | import brs.web.api.http.ApiServlet; 6 | import brs.web.api.http.common.JSONData; 7 | import brs.web.api.http.common.LegacyDocTag; 8 | import com.google.gson.JsonElement; 9 | 10 | import javax.servlet.http.HttpServletRequest; 11 | 12 | import static brs.web.api.http.common.Parameters.GOODS_PARAMETER; 13 | 14 | public final class GetDGSGood extends ApiServlet.JsonRequestHandler { 15 | 16 | private final ParameterService parameterService; 17 | 18 | public GetDGSGood(ParameterService parameterService) { 19 | super(new LegacyDocTag[] {LegacyDocTag.DGS}, GOODS_PARAMETER); 20 | this.parameterService = parameterService; 21 | } 22 | 23 | @Override 24 | protected 25 | JsonElement processRequest(HttpServletRequest req) throws SignumException { 26 | return JSONData.goods(parameterService.getGoods(req)); 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/brs/web/api/http/handler/GetDGSPurchase.java: -------------------------------------------------------------------------------- 1 | package brs.web.api.http.handler; 2 | 3 | import brs.SignumException; 4 | import brs.services.ParameterService; 5 | import brs.web.api.http.ApiServlet; 6 | import brs.web.api.http.common.JSONData; 7 | import brs.web.api.http.common.LegacyDocTag; 8 | import com.google.gson.JsonElement; 9 | 10 | import javax.servlet.http.HttpServletRequest; 11 | 12 | import static brs.web.api.http.common.Parameters.PURCHASE_PARAMETER; 13 | 14 | public final class GetDGSPurchase extends ApiServlet.JsonRequestHandler { 15 | 16 | private final ParameterService parameterService; 17 | 18 | public GetDGSPurchase(ParameterService parameterService) { 19 | super(new LegacyDocTag[] {LegacyDocTag.DGS}, PURCHASE_PARAMETER); 20 | this.parameterService = parameterService; 21 | } 22 | 23 | @Override 24 | protected 25 | JsonElement processRequest(HttpServletRequest req) throws SignumException { 26 | return JSONData.purchase(parameterService.getPurchase(req)); 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/brs/web/api/http/handler/GetMyInfo.java: -------------------------------------------------------------------------------- 1 | package brs.web.api.http.handler; 2 | 3 | import brs.web.api.http.ApiServlet; 4 | import brs.web.api.http.common.LegacyDocTag; 5 | import com.google.gson.JsonElement; 6 | import com.google.gson.JsonObject; 7 | 8 | import java.util.UUID; 9 | 10 | import javax.servlet.http.HttpServletRequest; 11 | 12 | public final class GetMyInfo extends ApiServlet.JsonRequestHandler { 13 | 14 | public static final GetMyInfo instance = new GetMyInfo(); 15 | 16 | private final String uuid; 17 | 18 | private GetMyInfo() { 19 | super(new LegacyDocTag[] {LegacyDocTag.INFO}); 20 | 21 | uuid = UUID.randomUUID().toString(); 22 | } 23 | 24 | @Override 25 | protected 26 | JsonElement processRequest(HttpServletRequest req) { 27 | 28 | JsonObject response = new JsonObject(); 29 | response.addProperty("host", req.getRemoteHost()); 30 | response.addProperty("address", req.getRemoteAddr()); 31 | response.addProperty("UUID", uuid); 32 | return response; 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/brs/web/api/http/handler/GetMyPeerInfo.java: -------------------------------------------------------------------------------- 1 | package brs.web.api.http.handler; 2 | 3 | import brs.TransactionProcessor; 4 | import brs.web.api.http.ApiServlet; 5 | import brs.web.api.http.common.LegacyDocTag; 6 | import com.google.gson.JsonElement; 7 | import com.google.gson.JsonObject; 8 | 9 | import javax.servlet.http.HttpServletRequest; 10 | 11 | public final class GetMyPeerInfo extends ApiServlet.JsonRequestHandler { 12 | 13 | private final TransactionProcessor transactionProcessor; 14 | 15 | public GetMyPeerInfo(TransactionProcessor transactionProcessor) { 16 | super(new LegacyDocTag[]{LegacyDocTag.PEER_INFO}); 17 | this.transactionProcessor = transactionProcessor; 18 | } 19 | 20 | @Override 21 | protected 22 | JsonElement processRequest(HttpServletRequest req) { 23 | 24 | JsonObject response = new JsonObject(); 25 | response.addProperty("utsInStore", transactionProcessor.getAmountUnconfirmedTransactions()); 26 | return response; 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/brs/web/api/http/handler/GetTime.java: -------------------------------------------------------------------------------- 1 | package brs.web.api.http.handler; 2 | 3 | import brs.services.TimeService; 4 | import brs.web.api.http.ApiServlet; 5 | import brs.web.api.http.common.LegacyDocTag; 6 | import com.google.gson.JsonElement; 7 | import com.google.gson.JsonObject; 8 | 9 | import javax.servlet.http.HttpServletRequest; 10 | 11 | import static brs.web.api.http.common.ResultFields.TIME_RESPONSE; 12 | 13 | public final class GetTime extends ApiServlet.JsonRequestHandler { 14 | 15 | private final TimeService timeService; 16 | 17 | public GetTime(TimeService timeService) { 18 | super(new LegacyDocTag[]{LegacyDocTag.INFO}); 19 | this.timeService = timeService; 20 | } 21 | 22 | @Override 23 | protected 24 | JsonElement processRequest(HttpServletRequest req) { 25 | JsonObject response = new JsonObject(); 26 | response.addProperty(TIME_RESPONSE, timeService.getEpochTime()); 27 | 28 | return response; 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/brs/web/api/ws/WebSocketConnection.java: -------------------------------------------------------------------------------- 1 | package brs.web.api.ws; 2 | 3 | import org.eclipse.jetty.websocket.api.RemoteEndpoint; 4 | import org.eclipse.jetty.websocket.api.Session; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | 8 | import java.io.IOException; 9 | 10 | public class WebSocketConnection { 11 | private static final Logger logger = LoggerFactory.getLogger(WebSocketConnection.class); 12 | 13 | private final Session session; 14 | 15 | public WebSocketConnection(Session session) { 16 | this.session = session; 17 | } 18 | 19 | public String getId() { 20 | return session.getRemoteAddress().toString(); 21 | } 22 | 23 | public Session getSession() { 24 | return session; 25 | } 26 | 27 | public void sendMessage(String message) { 28 | RemoteEndpoint remote = this.getSession().getRemote(); 29 | try { 30 | remote.sendString(message); 31 | } catch (IOException e) { 32 | logger.warn("Error sending message to {}: {}", remote.getRemoteAddress().toString(), e.getMessage()); 33 | } 34 | } 35 | 36 | public void close() { 37 | this.getSession().close(); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/brs/web/api/ws/WebSocketConnectionCreator.java: -------------------------------------------------------------------------------- 1 | package brs.web.api.ws; 2 | 3 | import brs.web.server.WebServerContext; 4 | import org.eclipse.jetty.websocket.server.JettyServerUpgradeRequest; 5 | import org.eclipse.jetty.websocket.server.JettyServerUpgradeResponse; 6 | import org.eclipse.jetty.websocket.server.JettyWebSocketCreator; 7 | 8 | public class WebSocketConnectionCreator implements JettyWebSocketCreator { 9 | 10 | private final WebServerContext context; 11 | 12 | public WebSocketConnectionCreator(WebServerContext context) { 13 | this.context = context; 14 | } 15 | 16 | @Override 17 | public Object createWebSocket(JettyServerUpgradeRequest jettyServerUpgradeRequest, JettyServerUpgradeResponse jettyServerUpgradeResponse) { 18 | return new WebSocketConnectionAdapter(this.context); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/brs/web/api/ws/common/BaseWebSocketResponse.java: -------------------------------------------------------------------------------- 1 | package brs.web.api.ws.common; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | 5 | public abstract class BaseWebSocketResponse<T> { 6 | 7 | @SerializedName("e") 8 | private final String eventName; 9 | @SerializedName("p") 10 | private final T payload; 11 | 12 | public BaseWebSocketResponse(String eventName, T payload) { 13 | this.eventName = eventName; 14 | this.payload = payload; 15 | } 16 | 17 | public abstract String toString(); 18 | 19 | public T getPayload() { 20 | return payload; 21 | } 22 | 23 | public String getEventName() { 24 | return eventName; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/brs/web/api/ws/common/JSONWebSocketResponse.java: -------------------------------------------------------------------------------- 1 | package brs.web.api.ws.common; 2 | 3 | import com.google.gson.Gson; 4 | 5 | public class JSONWebSocketResponse<T> extends BaseWebSocketResponse<T> { 6 | public JSONWebSocketResponse(String eventName, T payload) { 7 | super(eventName, payload); 8 | } 9 | 10 | public JSONWebSocketResponse(String eventName) { 11 | super(eventName, null); 12 | } 13 | 14 | @Override 15 | public String toString() { 16 | Gson gson = new Gson(); 17 | return gson.toJson(this); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/brs/web/api/ws/common/WebsocketEventNames.java: -------------------------------------------------------------------------------- 1 | package brs.web.api.ws.common; 2 | 3 | public class WebsocketEventNames { 4 | public static final String CONNECTED = "CONNECTED"; 5 | public static final String BLOCK_PUSHED = "BLOCK_PUSHED"; 6 | public static final String PENDING_TRANSACTIONS_ADDED = "PENDING_TRANSACTIONS_ADDED"; 7 | public static final String HEARTBEAT = "HEARTBEAT"; 8 | } 9 | -------------------------------------------------------------------------------- /src/brs/web/api/ws/emitter/AbstractWebSocketEventEmitterImpl.java: -------------------------------------------------------------------------------- 1 | package brs.web.api.ws.emitter; 2 | 3 | import brs.web.api.ws.WebSocketConnection; 4 | 5 | public abstract class AbstractWebSocketEventEmitterImpl<T> implements WebSocketEventEmitter<T> { 6 | 7 | private final WebSocketConnection connection; 8 | 9 | protected AbstractWebSocketEventEmitterImpl(WebSocketConnection connection) { 10 | this.connection = connection; 11 | } 12 | 13 | public abstract void emit(T t); 14 | 15 | @Override 16 | public void emit() { 17 | // do nothing - optional implementation 18 | } 19 | 20 | public WebSocketConnection getConnection() { 21 | return connection; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/brs/web/api/ws/emitter/HeartBeatEventEmitter.java: -------------------------------------------------------------------------------- 1 | package brs.web.api.ws.emitter; 2 | 3 | import brs.web.api.ws.WebSocketConnection; 4 | import brs.web.api.ws.common.JSONWebSocketResponse; 5 | import brs.web.api.ws.common.WebsocketEventNames; 6 | 7 | public class HeartBeatEventEmitter extends AbstractWebSocketEventEmitterImpl<Void> { 8 | 9 | public HeartBeatEventEmitter(WebSocketConnection connection) { 10 | super(connection); 11 | } 12 | 13 | @Override 14 | public void emit(Void noop) { 15 | // no op 16 | } 17 | 18 | @Override 19 | public void emit(){ 20 | JSONWebSocketResponse<Void> response = new JSONWebSocketResponse<>( 21 | WebsocketEventNames.HEARTBEAT 22 | ); 23 | this.getConnection().sendMessage(response.toString()); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/brs/web/api/ws/emitter/WebSocketEventEmitter.java: -------------------------------------------------------------------------------- 1 | package brs.web.api.ws.emitter; 2 | 3 | public interface WebSocketEventEmitter<T> { 4 | 5 | void emit(T t); 6 | void emit(); 7 | } 8 | -------------------------------------------------------------------------------- /src/brs/web/api/ws/emitter/data/ConnectedEventData.java: -------------------------------------------------------------------------------- 1 | package brs.web.api.ws.emitter.data; 2 | 3 | public class ConnectedEventData { 4 | public String version; 5 | public int globalHeight; 6 | public int localHeight; 7 | public String networkName; 8 | } 9 | 10 | -------------------------------------------------------------------------------- /src/brs/web/server/ServerConnectorBuilder.java: -------------------------------------------------------------------------------- 1 | package brs.web.server; 2 | 3 | import org.eclipse.jetty.server.Server; 4 | import org.eclipse.jetty.server.ServerConnector; 5 | 6 | public interface ServerConnectorBuilder { 7 | 8 | ServerConnector build(Server server); 9 | 10 | } 11 | -------------------------------------------------------------------------------- /src/brs/web/server/ServerConnectorFactory.java: -------------------------------------------------------------------------------- 1 | package brs.web.server; 2 | 3 | import org.eclipse.jetty.server.Server; 4 | import org.eclipse.jetty.server.ServerConnector; 5 | import org.eclipse.jetty.servlet.ServletContextHandler; 6 | 7 | public class ServerConnectorFactory { 8 | 9 | private final WebServerContext context; 10 | private final Server server; 11 | 12 | public ServerConnectorFactory(WebServerContext context, Server server) { 13 | this.context = context; 14 | this.server = server; 15 | } 16 | 17 | public ServerConnector createHttpConnector() { 18 | return new ServerConnectorHttpBuilderImpl(context).build(server); 19 | } 20 | public ServerConnector createWebsocketConnector(ServletContextHandler servletContextHandler) { 21 | return new ServerConnectorWebsocketBuilderImpl(context, servletContextHandler).build(server); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/brs/web/server/WebServer.java: -------------------------------------------------------------------------------- 1 | package brs.web.server; 2 | 3 | public interface WebServer { 4 | 5 | void start() throws Exception; 6 | 7 | void shutdown(); 8 | } 9 | -------------------------------------------------------------------------------- /src/signum/net/TestnetNetwork2.java: -------------------------------------------------------------------------------- 1 | package signum.net; 2 | 3 | import brs.props.Props; 4 | 5 | public class TestnetNetwork2 extends TestnetNetwork { 6 | 7 | public TestnetNetwork2() { 8 | 9 | setProperty(Props.NETWORK_NAME, "Signum-TESTNET-2"); 10 | 11 | setProperty(Props.ADDRESS_PREFIX, "TS"); 12 | setProperty(Props.VALUE_SUFIX, "TSIGNA"); 13 | setProperty(Props.EXPERIMENTAL, "true"); 14 | 15 | setProperty(Props.P2P_PORT, "7124"); 16 | 17 | setProperty(Props.SMART_ATS_HEIGHT, "416060"); 18 | 19 | setProperty(Props.P2P_REBROADCAST_TO, "77.56.66.83"); 20 | setProperty(Props.P2P_BOOTSTRAP_PEERS, "77.56.66.83"); 21 | 22 | setProperty(Props.P2P_NUM_BOOTSTRAP_CONNECTIONS, "1"); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /test/java/brs/common/AbstractUnitTest.java: -------------------------------------------------------------------------------- 1 | package brs.common; 2 | 3 | import java.util.Arrays; 4 | import java.util.Collection; 5 | 6 | public abstract class AbstractUnitTest { 7 | @SafeVarargs 8 | protected final <T> Collection<T> mockCollection(T... items) { 9 | return Arrays.asList(items); 10 | } 11 | 12 | protected String stringWithLength(int length) { 13 | StringBuilder result = new StringBuilder(); 14 | 15 | for(int i = 0; i < length; i++) { 16 | result.append("a"); 17 | } 18 | 19 | return result.toString(); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /test/java/brs/common/JSONTestHelper.java: -------------------------------------------------------------------------------- 1 | package brs.common; 2 | 3 | import brs.util.JSON; 4 | import com.google.gson.JsonElement; 5 | 6 | import static brs.web.api.http.common.ResultFields.ERROR_CODE_RESPONSE; 7 | 8 | ; 9 | 10 | public class JSONTestHelper { 11 | 12 | public static int errorCode(JsonElement json) { 13 | return JSON.getAsInt(JSON.getAsJsonObject(json).get(ERROR_CODE_RESPONSE)); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /test/java/brs/common/TestConstants.java: -------------------------------------------------------------------------------- 1 | package brs.common; 2 | 3 | import brs.crypto.Crypto; 4 | 5 | import static brs.Constants.ONE_SIGNA; 6 | 7 | public class TestConstants { 8 | 9 | public static final String TEST_ACCOUNT_ID = "BURST-D95D-67CQ-8VDN-5EVAR"; 10 | 11 | public static final long TEST_ACCOUNT_NUMERIC_ID_PARSED = 4297397359864028267L; 12 | 13 | public static final String TEST_SECRET_PHRASE = "ach wie gut dass niemand weiss dass ich Rumpelstilzchen heiss"; 14 | 15 | public static final String TEST_PUBLIC_KEY = "6b223e427b2d44ef8fe2dcb64845d7d9790045167202f1849facef10398bd529"; 16 | 17 | public static final byte[] TEST_PUBLIC_KEY_BYTES = Crypto.getPublicKey(TEST_SECRET_PHRASE); 18 | 19 | public static final String TEST_ACCOUNT_NUMERIC_ID = "4297397359864028267"; 20 | 21 | public static final String DEADLINE = "400"; 22 | 23 | public static final String FEE = "" + ONE_SIGNA; 24 | 25 | public static final long TEN_SIGNA = ONE_SIGNA * 10; 26 | } 27 | -------------------------------------------------------------------------------- /test/java/brs/common/TestInfrastructure.java: -------------------------------------------------------------------------------- 1 | package brs.common; 2 | 3 | public class TestInfrastructure { 4 | 5 | public static final String IN_MEMORY_DB_URL = "jdbc:h2:mem:test;"; 6 | 7 | public static final int TEST_API_PORT = 8885; 8 | } 9 | -------------------------------------------------------------------------------- /test/java/brs/deeplink/DeeplinkQRCodeGeneratorTest.java: -------------------------------------------------------------------------------- 1 | package brs.deeplink; 2 | 3 | import brs.common.TestConstants; 4 | import brs.feesuggestions.FeeSuggestionType; 5 | import com.google.zxing.WriterException; 6 | import org.junit.Before; 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | import org.junit.runners.JUnit4; 10 | 11 | import java.awt.image.BufferedImage; 12 | 13 | import static org.junit.Assert.assertNotNull; 14 | 15 | @RunWith(JUnit4.class) 16 | public class DeeplinkQRCodeGeneratorTest { 17 | private DeeplinkQRCodeGenerator deeplinkQRCodeGenerator; 18 | 19 | @Before 20 | public void setUpDeeplinkQrCodeGeneratorTest() { 21 | deeplinkQRCodeGenerator = new DeeplinkQRCodeGenerator(); 22 | } 23 | 24 | @Test 25 | public void testDeeplinkQrCodeGenerator() throws WriterException { 26 | BufferedImage image = deeplinkQRCodeGenerator.generateRequestSignumDeepLinkQRCode(TestConstants.TEST_ACCOUNT_NUMERIC_ID, TestConstants.TEN_SIGNA, FeeSuggestionType.STANDARD, 0L, "Test!", true); 27 | assertNotNull(image); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /test/java/brs/util/TextUtilsTest.java: -------------------------------------------------------------------------------- 1 | package brs.util; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.junit.runners.JUnit4; 6 | 7 | import java.util.Locale; 8 | 9 | import static org.junit.Assert.assertFalse; 10 | import static org.junit.Assert.assertTrue; 11 | 12 | @RunWith(JUnit4.class) 13 | public class TextUtilsTest { 14 | @Test 15 | public void testIsInAlphabet() { 16 | assertFalse(TextUtils.isInAlphabet("This string should not be okay")); 17 | assertTrue(TextUtils.isInAlphabet("ThisStringShouldBeOkay")); 18 | assertFalse(TextUtils.isInAlphabet("ThisStringHasPunctuation!")); 19 | assertFalse(TextUtils.isInAlphabet(new String(new byte[]{0x00, 0x01, 0x02}))); 20 | 21 | Locale.setDefault(Locale.forLanguageTag("tr-TR")); 22 | assertTrue(TextUtils.isInAlphabet("ThisStringHasAnIInIt")); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /test/java/brs/web/api/http/handler/CreateATProgramTest.java: -------------------------------------------------------------------------------- 1 | package brs.web.api.http.handler; 2 | 3 | import org.junit.Test; 4 | 5 | public class CreateATProgramTest { 6 | 7 | @Test 8 | public void processRequest() { 9 | //TODO Add tests 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /test/java/brs/web/api/http/handler/GetRewardRecipientTest.java: -------------------------------------------------------------------------------- 1 | package brs.web.api.http.handler; 2 | 3 | import org.junit.Test; 4 | 5 | public class GetRewardRecipientTest { 6 | 7 | @Test 8 | public void processRequest() { 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /test/java/brs/web/api/http/handler/ParameterParserTest.java: -------------------------------------------------------------------------------- 1 | package brs.web.api.http.handler; 2 | 3 | public class ParameterParserTest { 4 | // TODO add tests 5 | } 6 | -------------------------------------------------------------------------------- /update-classic.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | UI_DIR=./html/ui 6 | if [[ ! -e $UI_DIR ]]; then 7 | echo "Cannot find $UI_DIR" 8 | echo "🚫 Please run this script in your signum-node root dir (aside signum-node executable)" 9 | exit 1 10 | fi 11 | 12 | echo "🛰 Updating Signum Classic Wallet to current release..." 13 | echo "⬇️ Downloading latest release..." 14 | git clone --depth 1 https://github.com/signum-network/signum-classic-wallet.git 15 | 16 | echo "📝 Updating code base..." 17 | cp -r signum-classic-wallet/src/* ./html/ui/classic/ 18 | 19 | echo "🛀 Cleaning up..." 20 | rm -rf signum-classic-wallet 21 | 22 | echo "✅ Classic Wallet has been updated." 23 | 24 | -------------------------------------------------------------------------------- /update-openapi.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo "🛰 Updating API Docs..." 4 | 5 | SPEC_FILE_URL=https://raw.githubusercontent.com/signum-network/signum-node/main/openapi/dist/signum-api.json 6 | OPENAPI_DIR=./html/api-doc 7 | if [[ ! -e $OPENAPI_DIR ]]; then 8 | echo "Cannot find $OPENAPI_DIR" 9 | echo "🚫 Please run this script in your signum-node root dir (aside signum-node executable)" 10 | exit 1 11 | fi 12 | 13 | curl -s $SPEC_FILE_URL -o $OPENAPI_DIR/signum-api.json 14 | 15 | echo "✅ API Docs have been updated." 16 | --------------------------------------------------------------------------------