├── .dockerignore ├── .editorconfig ├── .env.sample ├── .githooks └── pre-commit ├── .github └── workflows │ ├── heroku-deploy.yml │ ├── ktlint.yml │ └── test.yml ├── .gitignore ├── LICENSE ├── README.md ├── build.gradle.kts ├── buildSrc ├── .gitignore ├── build.gradle.kts └── src │ └── main │ └── kotlin │ ├── Dependencies.kt │ └── Versions.kt ├── createEncryptor_studio.sh ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── ktor-grpc ├── build.gradle.kts └── src │ └── main │ └── kotlin │ └── io │ └── newm │ └── ktor │ └── server │ └── grpc │ ├── EngineMain.kt │ └── GRPCApplicationEngine.kt ├── newm-chain-db ├── build.gradle.kts └── src │ └── main │ └── kotlin │ └── io │ └── newm │ └── chain │ ├── config │ └── Config.kt │ ├── database │ ├── entity │ │ ├── ChainBlock.kt │ │ ├── LedgerAddress.kt │ │ ├── LedgerAsset.kt │ │ ├── LedgerAssetMetadata.kt │ │ ├── LedgerUtxo.kt │ │ ├── LedgerUtxoAsset.kt │ │ ├── LedgerUtxoHistory.kt │ │ ├── MonitoredAddressChain.kt │ │ ├── PaymentStakeAddress.kt │ │ ├── RawTransaction.kt │ │ ├── StakeDelegation.kt │ │ ├── StakeRegistration.kt │ │ ├── TransactionLog.kt │ │ └── User.kt │ ├── migration │ │ ├── V10__AlterLedgerAssetMetadata.kt │ │ ├── V11__CreateLedgerUtxoHistory.kt │ │ ├── V12__AlterNativeAssetLogAddressTxLog.kt │ │ ├── V13__CreateMonitoredAddressChain.kt │ │ ├── V14__CleanupIndexes.kt │ │ ├── V15__CleanupIndexes.kt │ │ ├── V16__AlterLedgerUtxos.kt │ │ ├── V1__InitialCreation.kt │ │ ├── V2__CreateLedgerAssetMetadata.kt │ │ ├── V3__AlterLedgerUtxos.kt │ │ ├── V4__CreateUsers.kt │ │ ├── V5__AlterLedgerUtxos.kt │ │ ├── V6__CreateAddressTxLog.kt │ │ ├── V7__DropKeys.kt │ │ ├── V8__AlterLedgerAssets.kt │ │ └── V9__CreateNativeAssetLog.kt │ ├── repository │ │ ├── ChainRepository.kt │ │ ├── ChainRepositoryImpl.kt │ │ ├── LedgerRepository.kt │ │ ├── LedgerRepositoryImpl.kt │ │ ├── UsersRepository.kt │ │ └── UsersRepositoryImpl.kt │ └── table │ │ ├── AddressTxLogTable.kt │ │ ├── ChainTable.kt │ │ ├── LedgerAssetMetadataTable.kt │ │ ├── LedgerAssetsTable.kt │ │ ├── LedgerTable.kt │ │ ├── LedgerUtxoAssetsTable.kt │ │ ├── LedgerUtxosHistoryTable.kt │ │ ├── LedgerUtxosTable.kt │ │ ├── MonitoredAddressChainTable.kt │ │ ├── NativeAssetMonitorLogTable.kt │ │ ├── PaymentStakeAddressTable.kt │ │ ├── RawTransactionsTable.kt │ │ ├── StakeDelegationsTable.kt │ │ ├── StakeRegistrationsTable.kt │ │ ├── TransactionLogTable.kt │ │ └── UsersTable.kt │ ├── model │ ├── CliKey.kt │ ├── CliKeyPair.kt │ ├── CreatedUtxo.kt │ ├── NativeAsset.kt │ ├── SpentUtxo.kt │ └── Utxo.kt │ └── util │ └── DbKtx.kt ├── newm-chain-grpc ├── build.gradle.kts └── src │ └── main │ └── proto │ └── newm_chain.proto ├── newm-chain-util ├── build.gradle.kts └── src │ ├── main │ └── kotlin │ │ └── io │ │ └── newm │ │ └── chain │ │ └── util │ │ ├── Bech32.kt │ │ ├── Blake2b.kt │ │ ├── CardanoKtx.kt │ │ ├── Constants.kt │ │ ├── Sha3.kt │ │ └── VLQ.kt │ └── test │ └── kotlin │ └── io │ └── newm │ └── chain │ └── util │ └── PaymentAddressHashTests.kt ├── newm-chain ├── Dockerfile ├── README.md ├── build.gradle.kts ├── dbsetup.md ├── docker-compose.yml ├── initdb.d │ └── init-user-db.sh ├── src │ ├── main │ │ ├── kotlin │ │ │ └── io │ │ │ │ └── newm │ │ │ │ └── chain │ │ │ │ ├── Application.kt │ │ │ │ ├── cardano │ │ │ │ ├── AssetKtx.kt │ │ │ │ ├── ByronGenesis.kt │ │ │ │ ├── MetadataKtx.kt │ │ │ │ ├── Utils.kt │ │ │ │ └── address │ │ │ │ │ ├── Address.kt │ │ │ │ │ ├── AddressCredential.kt │ │ │ │ │ ├── BIP32PublicKey.kt │ │ │ │ │ └── curve25519 │ │ │ │ │ ├── Fe.kt │ │ │ │ │ ├── Ge.kt │ │ │ │ │ ├── GeAffine.kt │ │ │ │ │ ├── GeCached.kt │ │ │ │ │ ├── GeP1P1.kt │ │ │ │ │ ├── GePartial.kt │ │ │ │ │ ├── GePrecomp.kt │ │ │ │ │ ├── Helpers.kt │ │ │ │ │ └── Scalar64.kt │ │ │ │ ├── daemon │ │ │ │ ├── BlockDaemon.kt │ │ │ │ ├── DaemonsKoinModule.kt │ │ │ │ └── MonitorAddressDaemon.kt │ │ │ │ ├── database │ │ │ │ ├── DatabaseInit.kt │ │ │ │ └── DatabaseKoinModule.kt │ │ │ │ ├── di │ │ │ │ └── DependencyInjectionInstall.kt │ │ │ │ ├── grpc │ │ │ │ ├── GrpcConfig.kt │ │ │ │ ├── GrpcKoinModule.kt │ │ │ │ ├── JwtAuthorizationServerInterceptor.kt │ │ │ │ ├── NewmChainService.kt │ │ │ │ ├── StateQueryClientPool.kt │ │ │ │ └── TxSubmitClientPool.kt │ │ │ │ ├── ledger │ │ │ │ ├── LedgerKoinModule.kt │ │ │ │ ├── SubmittedTransactionCache.kt │ │ │ │ └── SubmittedTransactionCacheImpl.kt │ │ │ │ └── logging │ │ │ │ └── SentryInstall.kt │ │ └── resources │ │ │ ├── application.conf │ │ │ └── logback.xml │ └── test │ │ └── kotlin │ │ └── io │ │ └── newm │ │ └── chain │ │ └── cardano │ │ ├── AddressDerivationTest.kt │ │ ├── AssetMatchTest.kt │ │ ├── Cip68DatumTest.kt │ │ ├── DumpBlockTest.kt │ │ ├── ExtractStakeAddressTest.kt │ │ ├── JsonMetadataTest.kt │ │ └── WalletConnectionSigningVerificationTest.kt └── systemd │ ├── .env.example │ ├── newmchain.service │ └── startServer.sh ├── newm-objectpool ├── build.gradle.kts └── src │ └── main │ └── kotlin │ └── io │ └── newm │ └── objectpool │ ├── DefaultPool.kt │ └── ObjectPool.kt ├── newm-server ├── .gitignore ├── Dockerfile ├── ReadMe.md ├── build.gradle.kts ├── docker-compose.yml ├── images │ ├── gradle-settings.png │ ├── modules-setting.png │ └── project-setting.png ├── initdb.d │ └── init-user-db.sh └── src │ ├── integTest │ ├── kotlin │ │ └── io │ │ │ └── newm │ │ │ └── server │ │ │ ├── AuthTest.kt │ │ │ ├── HealthTest.kt │ │ │ ├── SongsTest.kt │ │ │ ├── StringExt.kt │ │ │ ├── TestContext.kt │ │ │ └── UserTest.kt │ └── resources │ │ ├── file_example.flac │ │ ├── garage.conf │ │ └── studio.conf │ ├── main │ ├── kotlin │ │ └── io │ │ │ └── newm │ │ │ └── server │ │ │ ├── Application.kt │ │ │ ├── auth │ │ │ ├── AuthenticationInstall.kt │ │ │ ├── AuthenticationKoinModule.kt │ │ │ ├── AuthenticationRoutes.kt │ │ │ ├── jwt │ │ │ │ ├── JwtConfig.kt │ │ │ │ ├── JwtData.kt │ │ │ │ ├── JwtRoutes.kt │ │ │ │ ├── JwtType.kt │ │ │ │ └── repo │ │ │ │ │ ├── JwtRepository.kt │ │ │ │ │ └── JwtRepositoryImpl.kt │ │ │ ├── oauth │ │ │ │ ├── OAuthRoutes.kt │ │ │ │ ├── model │ │ │ │ │ ├── OAuthLoginRequest.kt │ │ │ │ │ ├── OAuthTokens.kt │ │ │ │ │ └── OAuthType.kt │ │ │ │ └── repo │ │ │ │ │ ├── OAuthRepository.kt │ │ │ │ │ └── OAuthRepositoryImpl.kt │ │ │ ├── password │ │ │ │ ├── LoginRequest.kt │ │ │ │ ├── LoginResponse.kt │ │ │ │ └── PasswordAuthRoutes.kt │ │ │ └── twofactor │ │ │ │ ├── TwoFactorAuthRoutes.kt │ │ │ │ ├── database │ │ │ │ ├── TwoFactorAuthEntity.kt │ │ │ │ └── TwoFactorAuthTable.kt │ │ │ │ └── repo │ │ │ │ ├── TwoFactorAuthRepository.kt │ │ │ │ └── TwoFactorAuthRepositoryImpl.kt │ │ │ ├── aws │ │ │ ├── AwsKoinModule.kt │ │ │ ├── SqsMessageReceiver.kt │ │ │ ├── cloudfront │ │ │ │ └── CloudfrontAudioStreamData.kt │ │ │ └── s3 │ │ │ │ └── AwsS3Utils.kt │ │ │ ├── client │ │ │ ├── ClientKoinModule.kt │ │ │ └── auth │ │ │ │ ├── AppleMusicBearerAuth.kt │ │ │ │ ├── SoundCloudBearerAuth.kt │ │ │ │ ├── SpotifyBearerAuth.kt │ │ │ │ └── model │ │ │ │ └── TokenInfo.kt │ │ │ ├── config │ │ │ ├── ConfigKoinModule.kt │ │ │ ├── database │ │ │ │ ├── ConfigEntity.kt │ │ │ │ └── ConfigTable.kt │ │ │ └── repo │ │ │ │ ├── ConfigRepository.kt │ │ │ │ └── ConfigRepositoryImpl.kt │ │ │ ├── content │ │ │ └── ContentNegotiationInstall.kt │ │ │ ├── cors │ │ │ └── CorsInstall.kt │ │ │ ├── curator │ │ │ ├── CuratorInstall.kt │ │ │ ├── CuratorKoinModule.kt │ │ │ └── support │ │ │ │ ├── CuratorPlugin.kt │ │ │ │ ├── Ec2EnsembleProvider.kt │ │ │ │ └── FileEnsembleProvider.kt │ │ │ ├── database │ │ │ ├── DatabaseInit.kt │ │ │ ├── DatabaseKoinModule.kt │ │ │ └── migration │ │ │ │ ├── V10__CreateKeys.kt │ │ │ │ ├── V11__SongsUpdates.kt │ │ │ │ ├── V12__UsersUpdates.kt │ │ │ │ ├── V13__CreateConfig.kt │ │ │ │ ├── V14__CreateCollaborations.kt │ │ │ │ ├── V15__SongsUpdates.kt │ │ │ │ ├── V16__SongsUpdates.kt │ │ │ │ ├── V17__CollaborationsUpdates.kt │ │ │ │ ├── V18__ConfigUpdates.kt │ │ │ │ ├── V19__CollaborationsUpdates.kt │ │ │ │ ├── V1__InitialCreation.kt │ │ │ │ ├── V20__SongsUpdates.kt │ │ │ │ ├── V21__CollaborationsUpdates.kt │ │ │ │ ├── V22__CreateQuartzScheduler.kt │ │ │ │ ├── V23__ConfigUpdates.kt │ │ │ │ ├── V24__UsersUpdates.kt │ │ │ │ ├── V25__SongsUpdates.kt │ │ │ │ ├── V26__SongsUpdates.kt │ │ │ │ ├── V27__ConfigUpdates.kt │ │ │ │ ├── V28__UsersUpdates.kt │ │ │ │ ├── V29__UsersUpdates.kt │ │ │ │ ├── V2__SongsUpdates.kt │ │ │ │ ├── V30__SongsUpdates.kt │ │ │ │ ├── V31__ConfigUpdates.kt │ │ │ │ ├── V32__SongsUpdates.kt │ │ │ │ ├── V33__SongsUpdates.kt │ │ │ │ ├── V34__SongsUpdates.kt │ │ │ │ ├── V35__SongsUpdates.kt │ │ │ │ ├── V36__SongsUpdates.kt │ │ │ │ ├── V37__UsersUpdates.kt │ │ │ │ ├── V38__SongsUpdates.kt │ │ │ │ ├── V39__ConfigUpdates.kt │ │ │ │ ├── V3__SongsUpdates.kt │ │ │ │ ├── V40__SongsUpdates.kt │ │ │ │ ├── V41__CreateSongReceipts.kt │ │ │ │ ├── V42__UsersUpdates.kt │ │ │ │ ├── V43__UsersUpdates.kt │ │ │ │ ├── V44__CascadeFixes.kt │ │ │ │ ├── V45__CreateEarnings.kt │ │ │ │ ├── V46__SongsUpdates.kt │ │ │ │ ├── V47__CollaborationsUpdates.kt │ │ │ │ ├── V48__CreateSongErrorHistory.kt │ │ │ │ ├── V49__SongsUpdates.kt │ │ │ │ ├── V4__SongsUpdates.kt │ │ │ │ ├── V50__CreateWalletConnections.kt │ │ │ │ ├── V51__WalletConnectionsUpdates.kt │ │ │ │ ├── V52__CreateMarketplace.kt │ │ │ │ ├── V53__CreateReleases.kt │ │ │ │ ├── V54__MarketplaceUpdates.kt │ │ │ │ ├── V55__ConfigUpdates.kt │ │ │ │ ├── V56__UserSongMarketplaceUpdates.kt │ │ │ │ ├── V57__ConfigUpdates.kt │ │ │ │ ├── V58__ReleasesUpdates.kt │ │ │ │ ├── V59__MarketplaceUpdates.kt │ │ │ │ ├── V5__SongsUpdates.kt │ │ │ │ ├── V60__EarningsUpdates.kt │ │ │ │ ├── V61__CreateScriptAddressWhitelist.kt │ │ │ │ ├── V62__ConfigUpdates.kt │ │ │ │ ├── V63__UsersUpdates.kt │ │ │ │ ├── V64__ConfigUpdates.kt │ │ │ │ ├── V65__JwtsDrop.kt │ │ │ │ ├── V66__MarketplaceUpdates.kt │ │ │ │ ├── V67__SongsReleasesUpdates.kt │ │ │ │ ├── V68__CreateMintingStatusHistory.kt │ │ │ │ ├── V69__MarketplaceUpdates.kt │ │ │ │ ├── V6__UsersUpdates.kt │ │ │ │ ├── V70__MarketplaceUpdates.kt │ │ │ │ ├── V71__MarketplaceUpdates.kt │ │ │ │ ├── V72__CreateSongSmartLinks.kt │ │ │ │ ├── V73__UsersUpdates.kt │ │ │ │ ├── V74__UsersUpdates.kt │ │ │ │ ├── V75__ConfigUpdates.kt │ │ │ │ ├── V76__CollaborationsUpdates.kt │ │ │ │ ├── V77__ConfigUpdates.kt │ │ │ │ ├── V78__ReleasesUpdates.kt │ │ │ │ ├── V7__UsersUpdates.kt │ │ │ │ ├── V8__SongsUpdates.kt │ │ │ │ └── V9__UsersUpdates.kt │ │ │ ├── di │ │ │ └── DependencyInjectionInstall.kt │ │ │ ├── features │ │ │ ├── arweave │ │ │ │ ├── ArweaveKoinModule.kt │ │ │ │ ├── ktx │ │ │ │ │ └── SongExt.kt │ │ │ │ ├── model │ │ │ │ │ ├── UploadResponse.kt │ │ │ │ │ ├── WeaveFile.kt │ │ │ │ │ ├── WeaveProps.kt │ │ │ │ │ ├── WeaveRequest.kt │ │ │ │ │ ├── WeaveResponse.kt │ │ │ │ │ └── WeaveResponseItem.kt │ │ │ │ └── repo │ │ │ │ │ ├── ArweaveRepository.kt │ │ │ │ │ └── ArweaveRepositoryImpl.kt │ │ │ ├── cardano │ │ │ │ ├── CardanoKoinModule.kt │ │ │ │ ├── CardanoRoutes.kt │ │ │ │ ├── database │ │ │ │ │ ├── KeyEntity.kt │ │ │ │ │ ├── KeyTable.kt │ │ │ │ │ ├── ScriptAddressWhitelistEntity.kt │ │ │ │ │ └── ScriptAddressWhitelistTable.kt │ │ │ │ ├── model │ │ │ │ │ ├── CliKey.kt │ │ │ │ │ ├── CliKeyPair.kt │ │ │ │ │ ├── EncryptionRequest.kt │ │ │ │ │ ├── GetWalletSongsResponse.kt │ │ │ │ │ ├── Key.kt │ │ │ │ │ ├── KeyFilters.kt │ │ │ │ │ ├── NFTSong.kt │ │ │ │ │ ├── QueryPriceResponse.kt │ │ │ │ │ ├── ScriptAddressWhitelistRequest.kt │ │ │ │ │ ├── SubmitTransactionRequest.kt │ │ │ │ │ ├── SubmitTransactionResponse.kt │ │ │ │ │ ├── SubmitTxRequest.kt │ │ │ │ │ └── WalletSong.kt │ │ │ │ ├── parser │ │ │ │ │ └── NFTSongParser.kt │ │ │ │ └── repo │ │ │ │ │ ├── CardanoRepository.kt │ │ │ │ │ └── CardanoRepositoryImpl.kt │ │ │ ├── clientconfig │ │ │ │ └── ClientConfigurationRoutes.kt │ │ │ ├── cloudinary │ │ │ │ ├── CloudinaryKoinModule.kt │ │ │ │ ├── CloudinaryRoutes.kt │ │ │ │ └── model │ │ │ │ │ └── CloudinarySignResponse.kt │ │ │ ├── collaboration │ │ │ │ ├── CollaborationKoinModule.kt │ │ │ │ ├── CollaborationRoutes.kt │ │ │ │ ├── database │ │ │ │ │ ├── CollaborationEntity.kt │ │ │ │ │ └── CollaborationTable.kt │ │ │ │ ├── model │ │ │ │ │ ├── Collaboration.kt │ │ │ │ │ ├── CollaborationFilters.kt │ │ │ │ │ ├── CollaborationIdBody.kt │ │ │ │ │ ├── CollaborationReply.kt │ │ │ │ │ ├── CollaborationStatus.kt │ │ │ │ │ ├── Collaborator.kt │ │ │ │ │ └── CollaboratorFilters.kt │ │ │ │ └── repo │ │ │ │ │ ├── CollaborationRepository.kt │ │ │ │ │ └── CollaborationRepositoryImpl.kt │ │ │ ├── daemon │ │ │ │ ├── AwsSqsDaemon.kt │ │ │ │ ├── DaemonsKoinModule.kt │ │ │ │ └── QuartzSchedulerDaemon.kt │ │ │ ├── distribution │ │ │ │ ├── DistributionKoinModule.kt │ │ │ │ ├── DistributionRepository.kt │ │ │ │ ├── DistributionRoutes.kt │ │ │ │ ├── eveara │ │ │ │ │ └── EvearaDistributionRepositoryImpl.kt │ │ │ │ └── model │ │ │ │ │ ├── AddAlbumRequest.kt │ │ │ │ │ ├── AddAlbumResponse.kt │ │ │ │ │ ├── AddArtistRequest.kt │ │ │ │ │ ├── AddArtistResponse.kt │ │ │ │ │ ├── AddParticipantRequest.kt │ │ │ │ │ ├── AddParticipantResponse.kt │ │ │ │ │ ├── AddTrackResponse.kt │ │ │ │ │ ├── AddUserLabelRequest.kt │ │ │ │ │ ├── AddUserLabelResponse.kt │ │ │ │ │ ├── AddUserRequest.kt │ │ │ │ │ ├── AddUserResponse.kt │ │ │ │ │ ├── AddUserSubscriptionRequest.kt │ │ │ │ │ ├── AddUserSubscriptionResponse.kt │ │ │ │ │ ├── AlbumData.kt │ │ │ │ │ ├── AlbumPrice.kt │ │ │ │ │ ├── AlbumStatus.kt │ │ │ │ │ ├── Artist.kt │ │ │ │ │ ├── ArtistData.kt │ │ │ │ │ ├── Availability.kt │ │ │ │ │ ├── Country.kt │ │ │ │ │ ├── CoverImage.kt │ │ │ │ │ ├── DeleteUserLabelResponse.kt │ │ │ │ │ ├── DistributeFutureReleaseRequest.kt │ │ │ │ │ ├── DistributeReleaseRequest.kt │ │ │ │ │ ├── DistributeReleaseResponse.kt │ │ │ │ │ ├── DistributionOutletReleaseStatusResponse.kt │ │ │ │ │ ├── Error.kt │ │ │ │ │ ├── ErrorField.kt │ │ │ │ │ ├── EvearaArtist.kt │ │ │ │ │ ├── EvearaErrorResponse.kt │ │ │ │ │ ├── EvearaOutlet.kt │ │ │ │ │ ├── EvearaSimpleResponse.kt │ │ │ │ │ ├── FeaturedArtist.kt │ │ │ │ │ ├── Genre.kt │ │ │ │ │ ├── GetAlbumResponse.kt │ │ │ │ │ ├── GetArtistResponse.kt │ │ │ │ │ ├── GetCountriesResponse.kt │ │ │ │ │ ├── GetDateResponse.kt │ │ │ │ │ ├── GetGenresResponse.kt │ │ │ │ │ ├── GetLanguagesResponse.kt │ │ │ │ │ ├── GetOutletProfileNamesResponse.kt │ │ │ │ │ ├── GetOutletsResponse.kt │ │ │ │ │ ├── GetParticipantsResponse.kt │ │ │ │ │ ├── GetPayoutBalanceResponse.kt │ │ │ │ │ ├── GetPayoutHistoryResponse.kt │ │ │ │ │ ├── GetRolesResponse.kt │ │ │ │ │ ├── GetSmartLinksResponse.kt │ │ │ │ │ ├── GetTrackStatusResponse.kt │ │ │ │ │ ├── GetTracksResponse.kt │ │ │ │ │ ├── GetUserLabelResponse.kt │ │ │ │ │ ├── GetUserResponse.kt │ │ │ │ │ ├── GetUserSubscriptionResponse.kt │ │ │ │ │ ├── InitiatePayoutResponse.kt │ │ │ │ │ ├── LabelData.kt │ │ │ │ │ ├── Language.kt │ │ │ │ │ ├── Outlet.kt │ │ │ │ │ ├── OutletProfile.kt │ │ │ │ │ ├── OutletProfileName.kt │ │ │ │ │ ├── OutletReleaseStatus.kt │ │ │ │ │ ├── OutletStatus.kt │ │ │ │ │ ├── OutletStatusCode.kt │ │ │ │ │ ├── OutletsDetail.kt │ │ │ │ │ ├── Participant.kt │ │ │ │ │ ├── ParticipantData.kt │ │ │ │ │ ├── ParticipantX.kt │ │ │ │ │ ├── PayoutBalance.kt │ │ │ │ │ ├── PayoutHistory.kt │ │ │ │ │ ├── PayoutStatus.kt │ │ │ │ │ ├── PayoutStatusCode.kt │ │ │ │ │ ├── Preview.kt │ │ │ │ │ ├── PriceCode.kt │ │ │ │ │ ├── PriceCodeList.kt │ │ │ │ │ ├── ReleaseData.kt │ │ │ │ │ ├── Role.kt │ │ │ │ │ ├── RoleX.kt │ │ │ │ │ ├── SmartLink.kt │ │ │ │ │ ├── Sony360.kt │ │ │ │ │ ├── State.kt │ │ │ │ │ ├── Subscription.kt │ │ │ │ │ ├── SubscriptionDetails.kt │ │ │ │ │ ├── SubscriptionX.kt │ │ │ │ │ ├── Track.kt │ │ │ │ │ ├── TrackData.kt │ │ │ │ │ ├── TrackPrice.kt │ │ │ │ │ ├── TrackStatus.kt │ │ │ │ │ ├── TrackX.kt │ │ │ │ │ ├── UpdateArtistRequest.kt │ │ │ │ │ ├── UpdateArtistResponse.kt │ │ │ │ │ ├── UpdateTrackRequest.kt │ │ │ │ │ ├── UpdateUserLabelRequest.kt │ │ │ │ │ ├── UpdateUserLabelResponse.kt │ │ │ │ │ ├── UpdateUserRequest.kt │ │ │ │ │ ├── UserLabelData.kt │ │ │ │ │ ├── UserResponse.kt │ │ │ │ │ ├── UserSubscription.kt │ │ │ │ │ ├── UserSubscriptionOverview.kt │ │ │ │ │ ├── ValidateAlbumResponse.kt │ │ │ │ │ └── ValidateData.kt │ │ │ ├── doc │ │ │ │ └── DocumentationRoutes.kt │ │ │ ├── dripdropz │ │ │ │ ├── DripDropzModule.kt │ │ │ │ ├── model │ │ │ │ │ ├── AvailableToken.kt │ │ │ │ │ ├── CheckRequest.kt │ │ │ │ │ └── CheckResponse.kt │ │ │ │ └── repo │ │ │ │ │ ├── DripDropzRepository.kt │ │ │ │ │ └── DripDropzRepositoryImpl.kt │ │ │ ├── earnings │ │ │ │ ├── EarningsKoinModule.kt │ │ │ │ ├── EarningsRoutes.kt │ │ │ │ ├── daemon │ │ │ │ │ ├── MonitorClaimOrderJob.kt │ │ │ │ │ └── MonitorClaimOrderSchedulerDaemon.kt │ │ │ │ ├── database │ │ │ │ │ ├── ClaimOrderEntity.kt │ │ │ │ │ ├── ClaimOrdersTable.kt │ │ │ │ │ ├── EarningEntity.kt │ │ │ │ │ └── EarningsTable.kt │ │ │ │ ├── model │ │ │ │ │ ├── AddSongRoyaltyRequest.kt │ │ │ │ │ ├── ClaimOrder.kt │ │ │ │ │ ├── ClaimOrderRequest.kt │ │ │ │ │ ├── ClaimOrderStatus.kt │ │ │ │ │ ├── Earning.kt │ │ │ │ │ ├── GetEarningsBySongIdResponse.kt │ │ │ │ │ └── GetEarningsResponse.kt │ │ │ │ └── repo │ │ │ │ │ ├── EarningsRepository.kt │ │ │ │ │ └── EarningsRepositoryImpl.kt │ │ │ ├── email │ │ │ │ ├── EmailKoinModule.kt │ │ │ │ └── repo │ │ │ │ │ ├── EmailRepository.kt │ │ │ │ │ └── EmailRepositoryImpl.kt │ │ │ ├── idenfy │ │ │ │ ├── IdenfyKoinModule.kt │ │ │ │ ├── IdenfyRoutes.kt │ │ │ │ ├── model │ │ │ │ │ ├── IdenfyCreateSessionRequest.kt │ │ │ │ │ ├── IdenfyCreateSessionResponse.kt │ │ │ │ │ └── IdenfySessionResult.kt │ │ │ │ └── repo │ │ │ │ │ ├── IdenfyRepository.kt │ │ │ │ │ └── IdenfyRepositoryImpl.kt │ │ │ ├── marketplace │ │ │ │ ├── MarketplaceKoinModule.kt │ │ │ │ ├── MarketplaceRoutes.kt │ │ │ │ ├── builders │ │ │ │ │ ├── MarketplaceDatumBuilders.kt │ │ │ │ │ └── MarketplaceTransactionBuilder.kt │ │ │ │ ├── daemon │ │ │ │ │ └── MarketplaceMonitorDaemon.kt │ │ │ │ ├── database │ │ │ │ │ ├── MarketplaceArtistEntity.kt │ │ │ │ │ ├── MarketplaceBookmarkEntity.kt │ │ │ │ │ ├── MarketplaceBookmarkTable.kt │ │ │ │ │ ├── MarketplacePendingOrderEntity.kt │ │ │ │ │ ├── MarketplacePendingOrderTable.kt │ │ │ │ │ ├── MarketplacePendingSaleEntity.kt │ │ │ │ │ ├── MarketplacePendingSaleTable.kt │ │ │ │ │ ├── MarketplacePurchaseEntity.kt │ │ │ │ │ ├── MarketplacePurchaseTable.kt │ │ │ │ │ ├── MarketplaceSaleEntity.kt │ │ │ │ │ ├── MarketplaceSaleOwnerEntity.kt │ │ │ │ │ ├── MarketplaceSaleOwnerTable.kt │ │ │ │ │ └── MarketplaceSaleTable.kt │ │ │ │ ├── model │ │ │ │ │ ├── Artist.kt │ │ │ │ │ ├── ArtistFilters.kt │ │ │ │ │ ├── CostAmountConversions.kt │ │ │ │ │ ├── OrderAmountRequest.kt │ │ │ │ │ ├── OrderAmountResponse.kt │ │ │ │ │ ├── OrderFees.kt │ │ │ │ │ ├── OrderTransactionRequest.kt │ │ │ │ │ ├── OrderTransactionResponse.kt │ │ │ │ │ ├── QueueTransaction.kt │ │ │ │ │ ├── Sale.kt │ │ │ │ │ ├── SaleEndAmountRequest.kt │ │ │ │ │ ├── SaleEndAmountResponse.kt │ │ │ │ │ ├── SaleEndTransactionRequest.kt │ │ │ │ │ ├── SaleEndTransactionResponse.kt │ │ │ │ │ ├── SaleFilters.kt │ │ │ │ │ ├── SaleStartAmountRequest.kt │ │ │ │ │ ├── SaleStartAmountResponse.kt │ │ │ │ │ ├── SaleStartTransactionRequest.kt │ │ │ │ │ ├── SaleStartTransactionResponse.kt │ │ │ │ │ ├── SaleStatus.kt │ │ │ │ │ ├── SaleTransaction.kt │ │ │ │ │ ├── Token.kt │ │ │ │ │ └── Transaction.kt │ │ │ │ ├── parser │ │ │ │ │ └── MarketplaceUtxoParser.kt │ │ │ │ └── repo │ │ │ │ │ ├── MarketplaceRepository.kt │ │ │ │ │ └── MarketplaceRepositoryImpl.kt │ │ │ ├── minting │ │ │ │ ├── DistributeAndMintException.kt │ │ │ │ ├── ForceTrackToFailException.kt │ │ │ │ ├── MintingKoinModule.kt │ │ │ │ ├── MintingMessageReceiver.kt │ │ │ │ ├── MintingStatusSqsMessage.kt │ │ │ │ ├── database │ │ │ │ │ ├── MintingStatusHistoryTable.kt │ │ │ │ │ └── MintingStatusTransactionEntity.kt │ │ │ │ ├── model │ │ │ │ │ ├── MintInfo.kt │ │ │ │ │ └── MintingStatusTransactionModel.kt │ │ │ │ └── repo │ │ │ │ │ ├── MintingRepository.kt │ │ │ │ │ └── MintingRepositoryImpl.kt │ │ │ ├── model │ │ │ │ └── CountResponse.kt │ │ │ ├── nftcdn │ │ │ │ ├── NftCdnKoinModule.kt │ │ │ │ └── repo │ │ │ │ │ ├── NftCdnRepository.kt │ │ │ │ │ └── NftCdnRepositoryImpl.kt │ │ │ ├── playlist │ │ │ │ ├── PlaylistKoinModule.kt │ │ │ │ ├── PlaylistRoutes.kt │ │ │ │ ├── database │ │ │ │ │ ├── PlaylistEntity.kt │ │ │ │ │ ├── PlaylistTable.kt │ │ │ │ │ └── SongsInPlaylistsTable.kt │ │ │ │ ├── model │ │ │ │ │ ├── Playlist.kt │ │ │ │ │ ├── PlaylistFilters.kt │ │ │ │ │ └── PlaylistIdBody.kt │ │ │ │ └── repo │ │ │ │ │ ├── PlaylistRepository.kt │ │ │ │ │ └── PlaylistRepositoryImpl.kt │ │ │ ├── referralhero │ │ │ │ ├── ReferralHeroKoinModule.kt │ │ │ │ ├── model │ │ │ │ │ ├── CommonResponse.kt │ │ │ │ │ ├── ReferralHeroSubscriber.kt │ │ │ │ │ └── ReferralStatus.kt │ │ │ │ └── repo │ │ │ │ │ ├── ReferralHeroRepository.kt │ │ │ │ │ └── ReferralHeroRepositoryImpl.kt │ │ │ ├── release │ │ │ │ ├── ReleaseKoinModule.kt │ │ │ │ ├── model │ │ │ │ │ ├── SpotifyPlaylistRequest.kt │ │ │ │ │ ├── SpotifySearchResponse.kt │ │ │ │ │ ├── SpotifyTrackItem.kt │ │ │ │ │ └── Tracks.kt │ │ │ │ └── repo │ │ │ │ │ ├── OutletReleaseRepository.kt │ │ │ │ │ └── OutletReleaseRepositoryImpl.kt │ │ │ ├── scheduler │ │ │ │ ├── ArweaveCheckAndFundJob.kt │ │ │ │ ├── EvearaReleaseStatusJob.kt │ │ │ │ ├── EvearaSyncJob.kt │ │ │ │ ├── OutletReleaseStatusJob.kt │ │ │ │ ├── ReferralHeroSyncJob.kt │ │ │ │ └── SchedulerPoolingConnectionProvider.kt │ │ │ ├── song │ │ │ │ ├── AudioMessageReceiver.kt │ │ │ │ ├── SongKoinModule.kt │ │ │ │ ├── SongRoutes.kt │ │ │ │ ├── database │ │ │ │ │ ├── ReleaseEntity.kt │ │ │ │ │ ├── ReleaseTable.kt │ │ │ │ │ ├── SongEntity.kt │ │ │ │ │ ├── SongErrorHistoryTable.kt │ │ │ │ │ ├── SongReceiptEntity.kt │ │ │ │ │ ├── SongReceiptTable.kt │ │ │ │ │ ├── SongSmartLinkEntity.kt │ │ │ │ │ ├── SongSmartLinkTable.kt │ │ │ │ │ └── SongTable.kt │ │ │ │ ├── model │ │ │ │ │ ├── AudioEncodingStatus.kt │ │ │ │ │ ├── AudioMessage.kt │ │ │ │ │ ├── AudioStreamResponse.kt │ │ │ │ │ ├── AudioUploadReport.kt │ │ │ │ │ ├── MarketplaceStatus.kt │ │ │ │ │ ├── MintPaymentOption.kt │ │ │ │ │ ├── MintPaymentRequest.kt │ │ │ │ │ ├── MintPaymentResponse.kt │ │ │ │ │ ├── MintingStatus.kt │ │ │ │ │ ├── PaymentType.kt │ │ │ │ │ ├── RefundPaymentResponse.kt │ │ │ │ │ ├── Release.kt │ │ │ │ │ ├── ReleaseBarcodeType.kt │ │ │ │ │ ├── ReleaseType.kt │ │ │ │ │ ├── Song.kt │ │ │ │ │ ├── SongFilters.kt │ │ │ │ │ ├── SongIdBody.kt │ │ │ │ │ ├── SongReceipt.kt │ │ │ │ │ ├── SongSmartLink.kt │ │ │ │ │ └── StreamTokenAgreementRequest.kt │ │ │ │ └── repo │ │ │ │ │ ├── SongRepository.kt │ │ │ │ │ └── SongRepositoryImpl.kt │ │ │ ├── user │ │ │ │ ├── UserKoinModule.kt │ │ │ │ ├── UserRoutes.kt │ │ │ │ ├── database │ │ │ │ │ ├── UserEntity.kt │ │ │ │ │ └── UserTable.kt │ │ │ │ ├── model │ │ │ │ │ ├── User.kt │ │ │ │ │ ├── UserFilters.kt │ │ │ │ │ ├── UserIdBody.kt │ │ │ │ │ └── UserVerificationStatus.kt │ │ │ │ ├── oauth │ │ │ │ │ ├── OAuthUser.kt │ │ │ │ │ ├── OAuthUserProvider.kt │ │ │ │ │ └── providers │ │ │ │ │ │ ├── AppleUserProvider.kt │ │ │ │ │ │ ├── FacebookUserProvider.kt │ │ │ │ │ │ ├── GoogleUserProvider.kt │ │ │ │ │ │ └── LinkedInUserProvider.kt │ │ │ │ ├── repo │ │ │ │ │ ├── UserRepository.kt │ │ │ │ │ └── UserRepositoryImpl.kt │ │ │ │ └── verify │ │ │ │ │ ├── AppleMusicProfileUrlVerifier.kt │ │ │ │ │ ├── OutletProfileUrlVerifier.kt │ │ │ │ │ ├── SoundCloudProfileUrlVerifier.kt │ │ │ │ │ └── SpotifyProfileUrlVerifier.kt │ │ │ └── walletconnection │ │ │ │ ├── WalletConnectionKoinModule.kt │ │ │ │ ├── WalletConnectionRoutes.kt │ │ │ │ ├── database │ │ │ │ ├── WalletConnectionChallengeEntity.kt │ │ │ │ ├── WalletConnectionChallengeTable.kt │ │ │ │ ├── WalletConnectionEntity.kt │ │ │ │ └── WalletConnectionTable.kt │ │ │ │ ├── model │ │ │ │ ├── AnswerChallengeRequest.kt │ │ │ │ ├── AnswerChallengeResponse.kt │ │ │ │ ├── ChallengeMethod.kt │ │ │ │ ├── GenerateChallengeRequest.kt │ │ │ │ ├── GenerateChallengeResponse.kt │ │ │ │ └── WalletConnection.kt │ │ │ │ └── repo │ │ │ │ ├── WalletConnectionRepository.kt │ │ │ │ └── WalletConnectionRepositoryImpl.kt │ │ │ ├── forwarder │ │ │ └── ForwarderInstall.kt │ │ │ ├── health │ │ │ └── HealthCheckInstall.kt │ │ │ ├── ktx │ │ │ ├── AnyExt.kt │ │ │ ├── ApplicationCallExt.kt │ │ │ ├── ApplicationRequestExt.kt │ │ │ ├── HttpClientExt.kt │ │ │ ├── HttpResponseExt.kt │ │ │ ├── InterProcessMutexExt.kt │ │ │ ├── JwtProviderExt.kt │ │ │ ├── KeyExt.kt │ │ │ ├── LambdaExt.kt │ │ │ ├── SecureApplicationEnvironmentExt.kt │ │ │ ├── SqsExt.kt │ │ │ ├── StringExt.kt │ │ │ └── VerificationExt.kt │ │ │ ├── logging │ │ │ ├── CallLoggingInstall.kt │ │ │ ├── InitializeLogging.kt │ │ │ ├── RequestLogging.kt │ │ │ └── SentryInstall.kt │ │ │ ├── model │ │ │ ├── ClientPlatform.kt │ │ │ └── FilterCriteria.kt │ │ │ ├── recaptcha │ │ │ ├── RecaptchaHeaders.kt │ │ │ ├── RecaptchaKoinModule.kt │ │ │ ├── model │ │ │ │ ├── RecaptchaAssessmentRequest.kt │ │ │ │ └── RecaptchaAssessmentResponse.kt │ │ │ └── repo │ │ │ │ ├── RecaptchaRepository.kt │ │ │ │ └── RecaptchaRepositoryImpl.kt │ │ │ ├── security │ │ │ ├── KeyParser.kt │ │ │ └── PrivateKeyReader.kt │ │ │ ├── serialization │ │ │ └── SerializationModule.kt │ │ │ ├── staticcontent │ │ │ └── StaticContentRoutes.kt │ │ │ ├── statuspages │ │ │ ├── StatusPagesInstall.kt │ │ │ └── StatusResponse.kt │ │ │ └── typealiases │ │ │ └── TypeAliases.kt │ ├── mjml │ │ ├── email │ │ │ ├── 2fa-code-join.mjml │ │ │ ├── 2fa-code-reset.mjml │ │ │ ├── collab-invitation.mjml │ │ │ ├── kyc-pending.mjml │ │ │ ├── kyc-unverified.mjml │ │ │ ├── kyc-verified.mjml │ │ │ ├── mint-declined.mjml │ │ │ ├── mint-failed.mjml │ │ │ ├── mint-released.mjml │ │ │ ├── mint-started.mjml │ │ │ ├── mint-suceeded.mjml │ │ │ ├── password-changed.mjml │ │ │ ├── sale-ended.mjml │ │ │ ├── sale-sold-out.mjml │ │ │ └── sale-started.mjml │ │ └── readme.txt │ └── resources │ │ ├── application.conf │ │ ├── audio-mime-types.properties │ │ ├── email │ │ ├── 2fa-code-join.html │ │ ├── 2fa-code-reset.html │ │ ├── arweave-warning.html │ │ ├── collab-invitation.html │ │ ├── kyc-pending.html │ │ ├── kyc-unverified.html │ │ ├── kyc-verified.html │ │ ├── mint-declined.html │ │ ├── mint-failed.html │ │ ├── mint-released.html │ │ ├── mint-started.html │ │ ├── mint-succeeded.html │ │ ├── password-changed.html │ │ ├── sale-ended.html │ │ ├── sale-sold-out.html │ │ └── sale-started.html │ │ ├── idenfy-messages.properties │ │ ├── images │ │ └── qrcode-logo.png │ │ ├── logback.xml │ │ ├── monitor_orders_quartz.properties │ │ ├── openapi │ │ └── documentation.yaml │ │ ├── quartz.properties │ │ └── static │ │ ├── isrc-country-codes.json │ │ ├── predefined-moods.json │ │ └── stream-token-policy-ids.json │ └── test │ ├── kotlin │ └── io │ │ └── newm │ │ └── server │ │ ├── BaseApplicationTests.kt │ │ ├── TestApplication.kt │ │ ├── auth │ │ └── FakeAuthentication.kt │ │ ├── aws │ │ └── cloudfront │ │ │ └── CloudfrontAudioStreamDataTest.kt │ │ ├── features │ │ ├── arweave │ │ │ ├── ktx │ │ │ │ └── SongExtTest.kt │ │ │ └── repo │ │ │ │ └── ArweaveRepositoryTest.kt │ │ ├── cardano │ │ │ ├── CardanoRoutesTests.kt │ │ │ ├── OracleParseTests.kt │ │ │ └── parser │ │ │ │ └── NFTSongParserTests.kt │ │ ├── cloudinary │ │ │ └── CloudinaryRoutesTests.kt │ │ ├── collaborations │ │ │ └── CollaborationRoutesTests.kt │ │ ├── distribution │ │ │ └── eveara │ │ │ │ └── EvearaDistributionRepositoryTest.kt │ │ ├── earnings │ │ │ ├── EarningsRoutesTests.kt │ │ │ └── EarningsTest.kt │ │ ├── idenfy │ │ │ ├── IdenfyFakeServer.kt │ │ │ └── IdenfyRoutesTests.kt │ │ ├── marketplace │ │ │ └── MarketplaceRoutesTests.kt │ │ ├── minting │ │ │ ├── ArweaveTest.kt │ │ │ ├── MintingMessageReceiverTest.kt │ │ │ ├── MintingStatusSqsMessageTest.kt │ │ │ └── repo │ │ │ │ └── MintingRepositoryTest.kt │ │ ├── playlist │ │ │ ├── PlaylistRoutesTests.kt │ │ │ └── TestPlaylists.kt │ │ ├── release │ │ │ └── repo │ │ │ │ └── OutletReleaseRepositoryTest.kt │ │ ├── song │ │ │ ├── SongRepositoryTest.kt │ │ │ ├── SongRoutesTests.kt │ │ │ └── TestSongs.kt │ │ ├── user │ │ │ ├── OutletProfileUrlVerifiersTest.kt │ │ │ ├── TestUsers.kt │ │ │ └── UserRoutesTests.kt │ │ └── walletconnection │ │ │ └── WalletConnectionRoutesTest.kt │ │ ├── grpc │ │ └── GrpcTests.kt │ │ ├── json │ │ └── TestJsonDecoding.kt │ │ ├── security │ │ ├── KeyParserTest.kt │ │ └── PrivateKeyReaderTest.kt │ │ ├── staticcontent │ │ └── StaticRoutesTests.kt │ │ └── utils │ │ ├── CborParseTest.kt │ │ ├── HugeWavParseTest.kt │ │ └── ResourceOutgoingContent.kt │ └── resources │ ├── sample1.flac │ └── test-application.conf ├── newm-shared ├── build.gradle.kts └── src │ ├── main │ └── kotlin │ │ └── io │ │ └── newm │ │ └── shared │ │ ├── auth │ │ └── Password.kt │ │ ├── coroutine │ │ └── SupervisorScope.kt │ │ ├── daemon │ │ ├── Daemon.kt │ │ └── DaemonInstall.kt │ │ ├── exception │ │ └── HttpStatusException.kt │ │ ├── exposed │ │ └── ExposedArrays.kt │ │ ├── koin │ │ └── Inject.kt │ │ ├── ktx │ │ ├── ApplicationConfigExt.kt │ │ ├── ApplicationEnvironmentExt.kt │ │ ├── BigDecimalExt.kt │ │ ├── ByteArrayExt.kt │ │ ├── ByteReadChannelExt.kt │ │ ├── EntityClassExt.kt │ │ ├── InstantExt.kt │ │ ├── IntExt.kt │ │ ├── JsonPrimitiveExt.kt │ │ ├── LazyExt.kt │ │ ├── ListExt.kt │ │ ├── LocalDateTimeExt.kt │ │ ├── LoggerExt.kt │ │ ├── LongExt.kt │ │ ├── PropertiesExt.kt │ │ ├── RouteExt.kt │ │ ├── SecureRandomExt.kt │ │ ├── StringExt.kt │ │ └── TableExt.kt │ │ ├── serialization │ │ ├── BigDecimalSerializer.kt │ │ ├── BigIntegerSerializer.kt │ │ ├── DMYLocalDateSerializer.kt │ │ ├── LocalDateSerializer.kt │ │ ├── LocalDateTimeSerializer.kt │ │ ├── PasswordSerializer.kt │ │ └── UUIDSerializer.kt │ │ └── test │ │ └── TestUtils.kt │ └── test │ └── kotlin │ └── io │ └── newm │ └── shared │ └── ktx │ ├── IsValidEmailTests.kt │ ├── IsValidPasswordTests.kt │ ├── IsValidUrlTests.kt │ ├── JsonPrimitiveValueTests.kt │ ├── NameValidationTests.kt │ ├── StringFormatTests.kt │ ├── StringToDurationTests.kt │ └── VerifyHashTests.kt ├── newm-tx-builder ├── build.gradle.kts └── src │ ├── main │ └── kotlin │ │ └── io │ │ └── newm │ │ └── txbuilder │ │ ├── TransactionBuilder.kt │ │ └── ktx │ │ ├── CardanoEraKtx.kt │ │ ├── NativeAssetKtx.kt │ │ ├── NativeScriptKtx.kt │ │ ├── PlutusDataKtx.kt │ │ ├── PlutusLanguageKtx.kt │ │ ├── RedeemerKtx.kt │ │ ├── SigningKeyKtx.kt │ │ ├── TransactionBuilderResponseKtx.kt │ │ └── UtxoKtx.kt │ └── test │ ├── kotlin │ └── io │ │ └── newm │ │ └── txbuildertest │ │ ├── KeyTest.kt │ │ ├── MinUtxoTest.kt │ │ └── TransactionBuilderTest.kt │ └── resources │ └── .gitignore ├── settings.gradle.kts └── system.properties /.dockerignore: -------------------------------------------------------------------------------- 1 | # Ignore git and project files 2 | .git 3 | .github 4 | .githooks 5 | .cache 6 | .idea 7 | .vscode 8 | 9 | # Ignore compiled files since they are generated in container 10 | **/build/ 11 | **/*.class 12 | 13 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | [*.{kt,kts}] 2 | ktlint_standard_class-naming = disabled 3 | ktlint_standard_import-ordering = disabled 4 | ktlint_standard_no-wildcard-imports = disabled 5 | ktlint_standard_trailing-comma-on-call-site = disabled 6 | ktlint_standard_trailing-comma-on-declaration-site = disabled 7 | ktlint_standard_max-line-length = disabled 8 | ktlint_standard_multiline-expression-wrapping = disabled 9 | -------------------------------------------------------------------------------- /.env.sample: -------------------------------------------------------------------------------- 1 | NEWM_JWT_SECRET= 2 | DATABASE_JDBC_URL= 3 | DATABASE_PASSWORD= 4 | DATABASE_URL= 5 | DATABASE_USERNAME= 6 | FACEBOOK_CLIENT_ID= 7 | FACEBOOK_CLIENT_SECRET= 8 | GOOGLE_CLIENT_ID= 9 | GOOGLE_CLIENT_SECRET= 10 | LINKEDIN_CLIENT_ID= 11 | LINKEDIN_CLIENT_SECRET= -------------------------------------------------------------------------------- /.githooks/pre-commit: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | exec ktlint -F "**/*.kt" "**/*.kts" "!**/generated/**" -------------------------------------------------------------------------------- /.github/workflows/heroku-deploy.yml: -------------------------------------------------------------------------------- 1 | name: deploy to heroku 2 | on: 3 | push: 4 | branches: 5 | - master 6 | jobs: 7 | build: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: actions/checkout@v2 11 | - uses: akhileshns/heroku-deploy@v3.12.12 12 | with: 13 | heroku_api_key: ${{ secrets.HEROKU_API_KEY }} 14 | heroku_app_name: ${{ secrets.HEROKU_APP_NAME }} 15 | heroku_email: ${{ secrets.HEROKU_EMAIL }} -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | # We may start running these on docker in the future, 2 | # but I wanted to put something in place in the meantime 3 | name: test 4 | on: 5 | push: 6 | branches: 7 | - master 8 | pull_request: 9 | 10 | jobs: 11 | build: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: actions/checkout@v2 15 | - uses: actions/setup-java@v2 16 | with: 17 | distribution: 'zulu' 18 | java-version: '21' 19 | - name: run tests 20 | run: ./gradlew test -PisGithubActions -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled class file 2 | *.class 3 | 4 | # Log file 5 | *.log 6 | 7 | # BlueJ files 8 | *.ctxt 9 | 10 | # Mobile Tools for Java (J2ME) 11 | .mtj.tmp/ 12 | 13 | # Package Files # 14 | *.jar 15 | *.war 16 | *.nar 17 | *.ear 18 | *.zip 19 | *.tar.gz 20 | *.rar 21 | 22 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 23 | hs_err_pid* 24 | 25 | #project files 26 | .gradle 27 | .idea 28 | .kotlin 29 | 30 | # Build files 31 | build 32 | 33 | .env 34 | 35 | # test files 36 | startServer.sh 37 | stopServer.sh 38 | *_localhost.sh 39 | *_garage.sh 40 | *_studio.sh 41 | *_studio_usd.sh 42 | *_studio_newmies.sh 43 | 44 | .elasticbeanstalk 45 | 46 | # key files 47 | *.skey 48 | *.vkey 49 | -------------------------------------------------------------------------------- /buildSrc/.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | -------------------------------------------------------------------------------- /buildSrc/build.gradle.kts: -------------------------------------------------------------------------------- 1 | repositories { 2 | mavenCentral() 3 | } 4 | 5 | plugins { 6 | `kotlin-dsl` 7 | } 8 | -------------------------------------------------------------------------------- /createEncryptor_studio.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | #get a JWT token 4 | EMAIL=$1 5 | PASSWORD=$2 6 | ESALT=$3 7 | EPASSWORD=$4 8 | 9 | ACCESS_TOKEN=`curl -X POST -H "Content-Type: application/json" -H "Accept: application/json" -d "{\"email\":\"${EMAIL}\",\"password\":\"${PASSWORD}\"}" https://studio.newm.io/v1/auth/login 2>/dev/null | jq -r .accessToken` 10 | #echo "accessToken: $ACCESS_TOKEN" 11 | 12 | cat > /tmp/create_encryptor.json << EOF 13 | { 14 | "s": "$ESALT", 15 | "password": "$EPASSWORD" 16 | } 17 | EOF 18 | 19 | curl -X POST --verbose -H "Content-Type: application/json" -H "Accept: application/json" -H "Authorization: Bearer $ACCESS_TOKEN" -d "@/tmp/create_encryptor.json" https://studio.newm.io/v1/cardano/encryption 2>/dev/null | jq . 20 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | kotlin.code.style=official 2 | org.gradle.jvmargs=-Dfile.encoding=UTF-8 \ 3 | --add-opens jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED \ 4 | --add-opens jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED \ 5 | --add-opens jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED \ 6 | --add-opens jdk.compiler/com.sun.tools.javac.jvm=ALL-UNNAMED \ 7 | --add-opens jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED \ 8 | --add-opens jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED \ 9 | --add-opens jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED \ 10 | --add-opens jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED 11 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectNEWM/newm-server/a96fc7499e5b2610bbb66cc1a305b26fa86ec2b0/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.14-bin.zip 4 | networkTimeout=10000 5 | validateDistributionUrl=true 6 | zipStoreBase=GRADLE_USER_HOME 7 | zipStorePath=wrapper/dists 8 | -------------------------------------------------------------------------------- /newm-chain-db/src/main/kotlin/io/newm/chain/config/Config.kt: -------------------------------------------------------------------------------- 1 | package io.newm.chain.config 2 | 3 | import io.newm.chain.util.Constants.NETWORK_MAGIC_MAINNET 4 | import io.newm.kogmios.protocols.model.result.ShelleyGenesisConfigResult 5 | 6 | object Config { 7 | lateinit var genesis: ShelleyGenesisConfigResult 8 | val isMainnet: Boolean by lazy { genesis.networkMagic == NETWORK_MAGIC_MAINNET } 9 | 10 | lateinit var shelleyGenesisHash: String 11 | } 12 | -------------------------------------------------------------------------------- /newm-chain-db/src/main/kotlin/io/newm/chain/database/entity/LedgerAddress.kt: -------------------------------------------------------------------------------- 1 | package io.newm.chain.database.entity 2 | 3 | import kotlinx.serialization.Serializable 4 | 5 | @Serializable 6 | data class LedgerAddress( 7 | val id: Long? = null, 8 | val address: String, 9 | val stakeAddress: String?, 10 | val addressType: String, 11 | ) 12 | -------------------------------------------------------------------------------- /newm-chain-db/src/main/kotlin/io/newm/chain/database/entity/LedgerAsset.kt: -------------------------------------------------------------------------------- 1 | package io.newm.chain.database.entity 2 | 3 | import kotlinx.serialization.Contextual 4 | import kotlinx.serialization.Serializable 5 | import kotlinx.serialization.Transient 6 | import java.math.BigInteger 7 | 8 | @Serializable 9 | data class LedgerAsset( 10 | val id: Long? = null, 11 | // policy id for this asset 12 | val policy: String, 13 | // name for this asset 14 | val name: String, 15 | // the total supply of this asset 16 | @Contextual 17 | val supply: BigInteger, 18 | @Transient 19 | val txId: String = "", 20 | ) 21 | -------------------------------------------------------------------------------- /newm-chain-db/src/main/kotlin/io/newm/chain/database/entity/LedgerAssetMetadata.kt: -------------------------------------------------------------------------------- 1 | package io.newm.chain.database.entity 2 | 3 | import kotlinx.serialization.Serializable 4 | 5 | @Serializable 6 | data class LedgerAssetMetadata( 7 | val id: Long? = null, 8 | val assetId: Long, 9 | val keyType: String, 10 | val key: String, 11 | val valueType: String, 12 | val value: String, 13 | val nestLevel: Int = 0, 14 | val children: List = emptyList(), 15 | ) 16 | -------------------------------------------------------------------------------- /newm-chain-db/src/main/kotlin/io/newm/chain/database/entity/LedgerUtxo.kt: -------------------------------------------------------------------------------- 1 | package io.newm.chain.database.entity 2 | 3 | import kotlinx.serialization.Contextual 4 | import kotlinx.serialization.Serializable 5 | import java.math.BigInteger 6 | 7 | @Serializable 8 | data class LedgerUtxo( 9 | val id: Long? = null, 10 | val ledgerId: Long, 11 | val txId: String, 12 | val txIx: Int, 13 | @Contextual val lovelace: BigInteger, 14 | val blockCreated: Long, 15 | val slotCreated: Long, 16 | val blockSpent: Long?, 17 | val slotSpent: Long?, 18 | val transactionSpent: String?, 19 | ) 20 | -------------------------------------------------------------------------------- /newm-chain-db/src/main/kotlin/io/newm/chain/database/entity/LedgerUtxoAsset.kt: -------------------------------------------------------------------------------- 1 | package io.newm.chain.database.entity 2 | 3 | import kotlinx.serialization.Contextual 4 | import kotlinx.serialization.Serializable 5 | import java.math.BigInteger 6 | 7 | @Serializable 8 | data class LedgerUtxoAsset( 9 | val id: Long? = null, 10 | val ledgerUtxoId: Long, 11 | val ledgerAssetId: Long, 12 | @Contextual val amount: BigInteger, 13 | ) 14 | -------------------------------------------------------------------------------- /newm-chain-db/src/main/kotlin/io/newm/chain/database/entity/LedgerUtxoHistory.kt: -------------------------------------------------------------------------------- 1 | package io.newm.chain.database.entity 2 | 3 | import kotlinx.serialization.Serializable 4 | 5 | @Serializable 6 | data class LedgerUtxoHistory( 7 | val paymentCred: String, 8 | val stakeCred: String?, 9 | val txId: String, 10 | val block: Long, 11 | ) 12 | -------------------------------------------------------------------------------- /newm-chain-db/src/main/kotlin/io/newm/chain/database/entity/MonitoredAddressChain.kt: -------------------------------------------------------------------------------- 1 | package io.newm.chain.database.entity 2 | 3 | data class MonitoredAddressChain( 4 | val id: Long? = null, 5 | val address: String, 6 | val height: Long, 7 | val slot: Long, 8 | val hash: String, 9 | ) 10 | -------------------------------------------------------------------------------- /newm-chain-db/src/main/kotlin/io/newm/chain/database/entity/PaymentStakeAddress.kt: -------------------------------------------------------------------------------- 1 | package io.newm.chain.database.entity 2 | 3 | data class PaymentStakeAddress( 4 | val id: Long? = null, 5 | val receivingAddress: String, 6 | val stakeAddress: String, 7 | ) 8 | -------------------------------------------------------------------------------- /newm-chain-db/src/main/kotlin/io/newm/chain/database/entity/StakeDelegation.kt: -------------------------------------------------------------------------------- 1 | package io.newm.chain.database.entity 2 | 3 | data class StakeDelegation( 4 | val id: Long? = null, 5 | // the block in which this delegation/deregistration occurred 6 | val blockNumber: Long, 7 | // the user's stake address 8 | val stakeAddress: String, 9 | // the epoch when the user last dripped this token 10 | val epoch: Long, 11 | // the pool id the user delegated to. null if this is a de-registration of the stake address 12 | val poolId: String?, 13 | ) { 14 | val isRegistration: Boolean by lazy { poolId != null } 15 | } 16 | -------------------------------------------------------------------------------- /newm-chain-db/src/main/kotlin/io/newm/chain/database/entity/StakeRegistration.kt: -------------------------------------------------------------------------------- 1 | package io.newm.chain.database.entity 2 | 3 | data class StakeRegistration( 4 | val id: Long? = null, 5 | // the user's stake address 6 | val stakeAddress: String, 7 | // the slot where the stake key registration happened 8 | val slot: Long, 9 | // the transaction index inside the block where the stake key registration happened 10 | val txIndex: Int, 11 | // the certificate index inside the transaction where the stake key registration happened 12 | val certIndex: Int, 13 | ) 14 | -------------------------------------------------------------------------------- /newm-chain-db/src/main/kotlin/io/newm/chain/database/entity/TransactionLog.kt: -------------------------------------------------------------------------------- 1 | package io.newm.chain.database.entity 2 | 3 | data class TransactionLog( 4 | val id: Long? = null, 5 | val transactionId: String, 6 | val cbor: String, 7 | val mintingPolicy: String?, 8 | val timestamp: String, 9 | val result: String, 10 | ) 11 | -------------------------------------------------------------------------------- /newm-chain-db/src/main/kotlin/io/newm/chain/database/entity/User.kt: -------------------------------------------------------------------------------- 1 | package io.newm.chain.database.entity 2 | 3 | data class User( 4 | val id: Long? = null, 5 | val name: String, 6 | ) 7 | -------------------------------------------------------------------------------- /newm-chain-db/src/main/kotlin/io/newm/chain/database/migration/V15__CleanupIndexes.kt: -------------------------------------------------------------------------------- 1 | package io.newm.chain.database.migration 2 | 3 | import org.flywaydb.core.api.migration.BaseJavaMigration 4 | import org.flywaydb.core.api.migration.Context 5 | import org.jetbrains.exposed.sql.transactions.transaction 6 | 7 | @Suppress("unused") 8 | class V15__CleanupIndexes : BaseJavaMigration() { 9 | override fun migrate(context: Context?) { 10 | transaction { 11 | execInBatch( 12 | listOf( 13 | """ 14 | CREATE INDEX IF NOT EXISTS "ledger_stake_address_index" ON "ledger" (stake_address) 15 | """.trimIndent(), 16 | ) 17 | ) 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /newm-chain-db/src/main/kotlin/io/newm/chain/database/migration/V16__AlterLedgerUtxos.kt: -------------------------------------------------------------------------------- 1 | package io.newm.chain.database.migration 2 | 3 | import org.flywaydb.core.api.migration.BaseJavaMigration 4 | import org.flywaydb.core.api.migration.Context 5 | import org.jetbrains.exposed.sql.transactions.transaction 6 | 7 | @Suppress("unused") 8 | class V16__AlterLedgerUtxos : BaseJavaMigration() { 9 | override fun migrate(context: Context?) { 10 | transaction { 11 | execInBatch( 12 | listOf( 13 | """ 14 | ALTER TABLE "ledger_utxos" ADD COLUMN "script_ref_version" INTEGER 15 | """.trimIndent(), 16 | ) 17 | ) 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /newm-chain-db/src/main/kotlin/io/newm/chain/database/migration/V5__AlterLedgerUtxos.kt: -------------------------------------------------------------------------------- 1 | package io.newm.chain.database.migration 2 | 3 | import org.flywaydb.core.api.migration.BaseJavaMigration 4 | import org.flywaydb.core.api.migration.Context 5 | import org.jetbrains.exposed.sql.transactions.transaction 6 | 7 | @Suppress("unused") 8 | class V5__AlterLedgerUtxos : BaseJavaMigration() { 9 | override fun migrate(context: Context?) { 10 | transaction { 11 | execInBatch( 12 | listOf( 13 | """ 14 | ALTER TABLE "ledger_utxos" ADD COLUMN "script_ref" TEXT 15 | """.trimIndent(), 16 | ) 17 | ) 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /newm-chain-db/src/main/kotlin/io/newm/chain/database/repository/UsersRepository.kt: -------------------------------------------------------------------------------- 1 | package io.newm.chain.database.repository 2 | 3 | import io.newm.chain.database.entity.User 4 | 5 | interface UsersRepository { 6 | fun get(userId: Long): User? 7 | 8 | fun getByName(name: String): User? 9 | 10 | fun insert(user: User): Long 11 | 12 | fun update(user: User): Int 13 | } 14 | -------------------------------------------------------------------------------- /newm-chain-db/src/main/kotlin/io/newm/chain/database/table/AddressTxLogTable.kt: -------------------------------------------------------------------------------- 1 | package io.newm.chain.database.table 2 | 3 | import org.jetbrains.exposed.dao.id.LongIdTable 4 | import org.jetbrains.exposed.sql.Column 5 | 6 | object AddressTxLogTable : LongIdTable(name = "address_tx_log") { 7 | val address: Column = text("address") 8 | val txId: Column = text("tx_id") 9 | val monitorAddressResponseBytes: Column = binary("monitor_address_response") 10 | val blockNumber: Column = long("block_number") 11 | } 12 | -------------------------------------------------------------------------------- /newm-chain-db/src/main/kotlin/io/newm/chain/database/table/LedgerAssetsTable.kt: -------------------------------------------------------------------------------- 1 | package io.newm.chain.database.table 2 | 3 | import org.jetbrains.exposed.dao.id.LongIdTable 4 | import org.jetbrains.exposed.sql.Column 5 | 6 | object LedgerAssetsTable : LongIdTable(name = "ledger_assets") { 7 | // policy id for this asset 8 | val policy: Column = text("policy") 9 | 10 | // name for this asset 11 | val name: Column = text("name") 12 | 13 | // the total supply of this asset 14 | val supply: Column = text("supply") 15 | } 16 | -------------------------------------------------------------------------------- /newm-chain-db/src/main/kotlin/io/newm/chain/database/table/LedgerTable.kt: -------------------------------------------------------------------------------- 1 | package io.newm.chain.database.table 2 | 3 | import org.jetbrains.exposed.dao.id.LongIdTable 4 | import org.jetbrains.exposed.sql.Column 5 | 6 | object LedgerTable : LongIdTable(name = "ledger") { 7 | // Address that holds utxos on the ledger 8 | val address: Column = text("address") 9 | 10 | // Stake address portion of the address (optional) 11 | val stakeAddress: Column = text("stake_address").nullable() 12 | 13 | // hex byte that determines the type of address this is 14 | val addressType: Column = varchar("address_type", 2) 15 | } 16 | -------------------------------------------------------------------------------- /newm-chain-db/src/main/kotlin/io/newm/chain/database/table/LedgerUtxoAssetsTable.kt: -------------------------------------------------------------------------------- 1 | package io.newm.chain.database.table 2 | 3 | import org.jetbrains.exposed.dao.id.LongIdTable 4 | import org.jetbrains.exposed.sql.Column 5 | 6 | object LedgerUtxoAssetsTable : LongIdTable(name = "ledger_utxo_assets") { 7 | val ledgerUtxoId: Column = long("ledger_utxo_id").references(LedgerUtxosTable.id) 8 | val ledgerAssetId: Column = long("ledger_asset_id").references(LedgerAssetsTable.id) 9 | val amount: Column = text("amount") 10 | } 11 | -------------------------------------------------------------------------------- /newm-chain-db/src/main/kotlin/io/newm/chain/database/table/LedgerUtxosHistoryTable.kt: -------------------------------------------------------------------------------- 1 | package io.newm.chain.database.table 2 | 3 | import org.jetbrains.exposed.sql.Column 4 | import org.jetbrains.exposed.sql.Table 5 | 6 | object LedgerUtxosHistoryTable : Table(name = "ledger_utxos_history") { 7 | // credential 8 | val paymentCred: Column = text("payment_cred") 9 | val stakeCred: Column = text("stake_cred").nullable() 10 | 11 | // transaction id 12 | val txId: Column = text("tx_id") 13 | 14 | // the block number 15 | val block: Column = long("block") 16 | } 17 | -------------------------------------------------------------------------------- /newm-chain-db/src/main/kotlin/io/newm/chain/database/table/MonitoredAddressChainTable.kt: -------------------------------------------------------------------------------- 1 | package io.newm.chain.database.table 2 | 3 | import org.jetbrains.exposed.dao.id.LongIdTable 4 | import org.jetbrains.exposed.sql.Column 5 | 6 | object MonitoredAddressChainTable : LongIdTable(name = "monitored_address_chain") { 7 | // the address 8 | val address: Column = text("address") 9 | 10 | // the height 11 | val height: Column = long("height") 12 | 13 | // the slot 14 | val slot: Column = long("slot") 15 | 16 | // the hash 17 | val hash: Column = text("hash") 18 | } 19 | -------------------------------------------------------------------------------- /newm-chain-db/src/main/kotlin/io/newm/chain/database/table/NativeAssetMonitorLogTable.kt: -------------------------------------------------------------------------------- 1 | package io.newm.chain.database.table 2 | 3 | import org.jetbrains.exposed.dao.id.LongIdTable 4 | import org.jetbrains.exposed.sql.Column 5 | 6 | object NativeAssetMonitorLogTable : LongIdTable(name = "native_asset_log") { 7 | val monitorNativeAssetsResponseBytes: Column = binary("monitor_native_assets_response") 8 | val blockNumber: Column = long("block_number") 9 | } 10 | -------------------------------------------------------------------------------- /newm-chain-db/src/main/kotlin/io/newm/chain/database/table/PaymentStakeAddressTable.kt: -------------------------------------------------------------------------------- 1 | package io.newm.chain.database.table 2 | 3 | import org.jetbrains.exposed.dao.id.LongIdTable 4 | import org.jetbrains.exposed.sql.Column 5 | 6 | object PaymentStakeAddressTable : LongIdTable(name = "payment_stake_addresses") { 7 | val receivingAddress: Column = text("receiving_address") 8 | val stakeAddress: Column = text("stake_address") 9 | } 10 | -------------------------------------------------------------------------------- /newm-chain-db/src/main/kotlin/io/newm/chain/database/table/TransactionLogTable.kt: -------------------------------------------------------------------------------- 1 | package io.newm.chain.database.table 2 | 3 | import org.jetbrains.exposed.dao.id.LongIdTable 4 | import org.jetbrains.exposed.sql.Column 5 | 6 | object TransactionLogTable : LongIdTable(name = "transaction_log") { 7 | val transactionId: Column = text("transaction_id") 8 | val cbor: Column = text("cbor") 9 | val timestamp: Column = text("timestamp") 10 | val result: Column = text("result") 11 | } 12 | -------------------------------------------------------------------------------- /newm-chain-db/src/main/kotlin/io/newm/chain/database/table/UsersTable.kt: -------------------------------------------------------------------------------- 1 | package io.newm.chain.database.table 2 | 3 | import org.jetbrains.exposed.dao.id.LongIdTable 4 | import org.jetbrains.exposed.sql.Column 5 | 6 | object UsersTable : LongIdTable(name = "api_users") { 7 | val name: Column = text("name") 8 | } 9 | -------------------------------------------------------------------------------- /newm-chain-db/src/main/kotlin/io/newm/chain/model/CliKey.kt: -------------------------------------------------------------------------------- 1 | package io.newm.chain.model 2 | 3 | data class CliKey( 4 | val type: String, 5 | val description: String, 6 | val cborHex: String 7 | ) 8 | -------------------------------------------------------------------------------- /newm-chain-db/src/main/kotlin/io/newm/chain/model/CliKeyPair.kt: -------------------------------------------------------------------------------- 1 | package io.newm.chain.model 2 | 3 | data class CliKeyPair( 4 | val skey: CliKey, 5 | val vkey: CliKey, 6 | ) 7 | -------------------------------------------------------------------------------- /newm-chain-util/src/main/kotlin/io/newm/chain/util/Sha3.kt: -------------------------------------------------------------------------------- 1 | package io.newm.chain.util 2 | 3 | import org.bouncycastle.crypto.digests.SHA3Digest 4 | import kotlin.concurrent.getOrSet 5 | 6 | object Sha3 { 7 | private val sha3_256Container = ThreadLocal() 8 | 9 | /** 10 | * Sha3-256 hash 11 | */ 12 | fun hash256(input: ByteArray): ByteArray { 13 | val sha3Digest = sha3_256Container.getOrSet { SHA3Digest(256) } 14 | sha3Digest.update(input, 0, input.size) 15 | val hash = ByteArray(32) 16 | sha3Digest.doFinal(hash, 0) 17 | return hash 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /newm-chain/initdb.d/init-user-db.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL 5 | CREATE USER ${DATABASE_USERNAME}; 6 | CREATE DATABASE ${DATABASE_NAME}; 7 | ALTER USER ${DATABASE_USERNAME} WITH PASSWORD '${DATABASE_PASSWORD}'; 8 | ALTER USER ${DATABASE_USERNAME} VALID UNTIL 'infinity'; 9 | ALTER DATABASE ${DATABASE_NAME} OWNER TO ${DATABASE_USERNAME}; 10 | EOSQL 11 | 12 | -------------------------------------------------------------------------------- /newm-chain/src/main/kotlin/io/newm/chain/cardano/AssetKtx.kt: -------------------------------------------------------------------------------- 1 | package io.newm.chain.cardano 2 | 3 | import io.newm.kogmios.protocols.model.Asset 4 | 5 | /** 6 | * Canonical Cbor sort. Shorter name lengths first, then lexicographically 7 | */ 8 | fun List.sortedWithCanonicalCbor(): List = 9 | this.sortedWith { nativeAsset, other -> 10 | var comparison = nativeAsset.policyId.compareTo(other.policyId) 11 | if (comparison == 0) { 12 | comparison = nativeAsset.name.length.compareTo(other.name.length) 13 | if (comparison == 0) { 14 | comparison = nativeAsset.name.compareTo(other.name) 15 | } 16 | } 17 | comparison 18 | } 19 | -------------------------------------------------------------------------------- /newm-chain/src/main/kotlin/io/newm/chain/cardano/ByronGenesis.kt: -------------------------------------------------------------------------------- 1 | package io.newm.chain.cardano 2 | 3 | data class ByronGenesis( 4 | val startTime: Long, 5 | val protocolConsts: ProtocolConsts, 6 | val blockVersionData: BlockVersionData, 7 | ) 8 | 9 | data class ProtocolConsts( 10 | val k: Long 11 | ) 12 | 13 | data class BlockVersionData( 14 | val slotDuration: Long, 15 | ) 16 | -------------------------------------------------------------------------------- /newm-chain/src/main/kotlin/io/newm/chain/cardano/address/AddressCredential.kt: -------------------------------------------------------------------------------- 1 | package io.newm.chain.cardano.address 2 | 3 | import io.newm.chain.util.Blake2b 4 | 5 | class AddressCredential( 6 | val hash: ByteArray 7 | ) { 8 | companion object { 9 | fun fromKey(key: BIP32PublicKey): AddressCredential { 10 | val keyHash = Blake2b.hash224(key.pk) 11 | return AddressCredential(keyHash) 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /newm-chain/src/main/kotlin/io/newm/chain/cardano/address/curve25519/GeCached.kt: -------------------------------------------------------------------------------- 1 | package io.newm.chain.cardano.address.curve25519 2 | 3 | class GeCached( 4 | internal val yPlusX: Fe, 5 | internal val yMinusX: Fe, 6 | internal val z: Fe, 7 | internal val t2d: Fe 8 | ) 9 | -------------------------------------------------------------------------------- /newm-chain/src/main/kotlin/io/newm/chain/cardano/address/curve25519/GeP1P1.kt: -------------------------------------------------------------------------------- 1 | package io.newm.chain.cardano.address.curve25519 2 | 3 | data class GeP1P1( 4 | internal val x: Fe, 5 | internal val y: Fe, 6 | internal val z: Fe, 7 | internal val t: Fe 8 | ) { 9 | fun toFull(): Ge { 10 | val x = this.x * this.t 11 | val y = this.y * this.z 12 | val z = this.z * this.t 13 | val t = this.x * this.y 14 | return Ge(x, y, z, t) 15 | } 16 | 17 | fun toPartial(): GePartial { 18 | val x = this.x * this.t 19 | val y = this.y * this.z 20 | val z = this.z * this.t 21 | return GePartial(x, y, z) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /newm-chain/src/main/kotlin/io/newm/chain/cardano/address/curve25519/GePartial.kt: -------------------------------------------------------------------------------- 1 | package io.newm.chain.cardano.address.curve25519 2 | 3 | data class GePartial( 4 | internal val x: Fe, 5 | internal val y: Fe, 6 | internal val z: Fe 7 | ) { 8 | private fun doubleP1P1(): GeP1P1 { 9 | val xx = x.square() 10 | val yy = y.square() 11 | val b = z.squareAndDouble() 12 | val a = x + y 13 | val aa = a.square() 14 | val y3 = yy + xx 15 | val z3 = yy - xx 16 | val x3 = aa - y3 17 | val t3 = b - z3 18 | 19 | return GeP1P1(x3, y3, z3, t3) 20 | } 21 | 22 | fun double(): GePartial = doubleP1P1().toPartial() 23 | 24 | fun doubleFull(): Ge = doubleP1P1().toFull() 25 | } 26 | -------------------------------------------------------------------------------- /newm-chain/src/main/kotlin/io/newm/chain/daemon/DaemonsKoinModule.kt: -------------------------------------------------------------------------------- 1 | package io.newm.chain.daemon 2 | 3 | import io.newm.shared.daemon.Daemon 4 | import org.koin.core.qualifier.named 5 | import org.koin.dsl.bind 6 | import org.koin.dsl.module 7 | 8 | fun daemonsKoinModule(monitorAddresses: List) = 9 | module { 10 | single { 11 | BlockDaemon( 12 | get(), 13 | get(), 14 | get(), 15 | get(), 16 | get(named("confirmedBlockFlow")), 17 | ) 18 | } bind Daemon::class 19 | 20 | monitorAddresses.distinct().forEach { address -> 21 | single(named(address)) { MonitorAddressDaemon(get(), get(), get(), address) } bind Daemon::class 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /newm-chain/src/main/kotlin/io/newm/chain/database/DatabaseKoinModule.kt: -------------------------------------------------------------------------------- 1 | package io.newm.chain.database 2 | 3 | import io.newm.chain.database.repository.ChainRepository 4 | import io.newm.chain.database.repository.ChainRepositoryImpl 5 | import io.newm.chain.database.repository.LedgerRepository 6 | import io.newm.chain.database.repository.LedgerRepositoryImpl 7 | import io.newm.chain.database.repository.UsersRepository 8 | import io.newm.chain.database.repository.UsersRepositoryImpl 9 | import org.koin.dsl.module 10 | 11 | val databaseKoinModule = 12 | module { 13 | single { ChainRepositoryImpl() } 14 | single { LedgerRepositoryImpl() } 15 | single { UsersRepositoryImpl() } 16 | } 17 | -------------------------------------------------------------------------------- /newm-chain/src/main/kotlin/io/newm/chain/grpc/GrpcKoinModule.kt: -------------------------------------------------------------------------------- 1 | package io.newm.chain.grpc 2 | 3 | import org.koin.dsl.module 4 | 5 | val grpcKoinModule = 6 | module { 7 | single { TxSubmitClientPool(5) } 8 | single { StateQueryClientPool(5) } 9 | } 10 | -------------------------------------------------------------------------------- /newm-chain/src/main/kotlin/io/newm/chain/ledger/LedgerKoinModule.kt: -------------------------------------------------------------------------------- 1 | package io.newm.chain.ledger 2 | 3 | import io.newm.kogmios.protocols.model.Block 4 | import kotlinx.coroutines.channels.BufferOverflow 5 | import kotlinx.coroutines.flow.MutableSharedFlow 6 | import org.koin.core.qualifier.named 7 | import org.koin.dsl.bind 8 | import org.koin.dsl.module 9 | 10 | val ledgerKoinModule = 11 | module { 12 | single { SubmittedTransactionCacheImpl() } bind SubmittedTransactionCache::class 13 | single(qualifier = named("confirmedBlockFlow")) { 14 | MutableSharedFlow( 15 | replay = 100, 16 | onBufferOverflow = BufferOverflow.DROP_OLDEST 17 | ) 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /newm-chain/src/main/kotlin/io/newm/chain/ledger/SubmittedTransactionCache.kt: -------------------------------------------------------------------------------- 1 | package io.newm.chain.ledger 2 | 3 | interface SubmittedTransactionCache { 4 | val keys: Set 5 | 6 | fun put( 7 | txId: String, 8 | txSigned: ByteArray 9 | ) 10 | 11 | fun get(txId: String): ByteArray? 12 | 13 | fun forEach(action: (Map.Entry) -> Unit) 14 | } 15 | -------------------------------------------------------------------------------- /newm-chain/src/main/kotlin/io/newm/chain/logging/SentryInstall.kt: -------------------------------------------------------------------------------- 1 | package io.newm.chain.logging 2 | 3 | import io.ktor.server.application.Application 4 | import io.sentry.Sentry 5 | 6 | // FIXME: Extract this into a shared module 7 | fun Application.initializeSentry() { 8 | Sentry.init { options -> 9 | options.dsn = environment.config.property("sentry.dsn").getString() 10 | // options.tracesSampleRate = if (environment.developmentMode) 1.0 else 0.5 11 | options.tracesSampleRate = 1.0 12 | options.isDebug = this.developmentMode 13 | options.environment = environment.config.property("sentry.environment").getString() 14 | } 15 | } 16 | 17 | internal fun Throwable.captureToSentry() { 18 | Sentry.captureException(this) 19 | } 20 | -------------------------------------------------------------------------------- /newm-chain/src/test/kotlin/io/newm/chain/cardano/AssetMatchTest.kt: -------------------------------------------------------------------------------- 1 | package io.newm.chain.cardano 2 | 3 | import com.google.common.truth.Truth.assertThat 4 | import org.junit.jupiter.api.Test 5 | 6 | class AssetMatchTest { 7 | @Test 8 | fun `test asset regex matching`() { 9 | val assetName = "000643b05465737420426c6f623336" 10 | val cip68Regex = Regex("^000643b0.*$") // (100)TokenName 11 | assertThat(assetName.matches(cip68Regex)).isTrue() 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /newm-chain/systemd/newmchain.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=NewmChain - ChainSync and APIs for Cardano 3 | After=syslog.target 4 | StartLimitIntervalSec=0 5 | 6 | [Service] 7 | Type=simple 8 | Restart=always 9 | RestartSec=5 10 | User=westbam 11 | LimitNOFILE=131072 12 | WorkingDirectory=/home/westbam/haskell/newmchain 13 | EnvironmentFile=/home/westbam/haskell/newmchain/.env 14 | ExecStart=/usr/bin/java -XX:+DisableAttachMechanism -XX:+UnlockExperimentalVMOptions -XX:+UseZGC -Xmx8192m -jar newm-chain.jar 15 | SuccessExitStatus=143 16 | StandardOutput=syslog 17 | StandardError=syslog 18 | SyslogIdentifier=newmchain 19 | 20 | [Install] 21 | WantedBy=multi-user.target 22 | -------------------------------------------------------------------------------- /newm-chain/systemd/startServer.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # This script will start the service from the cmdline on systems that don't run 4 | # systemd. It looks for the .env file in the same folder to configure newm-chain 5 | 6 | set -a 7 | source <(sed -e "s/\r//" -e '/^#/d;/^\s*$/d' -e "s/'/'\\\''/g" -e "s/=\(.*\)/=\"\1\"/g" ".env") 8 | set +a 9 | 10 | /usr/bin/java -XX:+DisableAttachMechanism -XX:+UnlockExperimentalVMOptions -XX:+UseZGC -Xmx16384m -jar newm-chain.jar 2>&1 | sed 's/^.*\]: //g; s#WARN.*$#\x1b[33m&\x1b[0m#; s#ERROR.*$#\x1b[31m&\x1b[0m#; s#INFO#\x1b[32m&\x1b[0m#' 11 | -------------------------------------------------------------------------------- /newm-server/.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | gradlew.bat 3 | gradlew 4 | gradle/ -------------------------------------------------------------------------------- /newm-server/ReadMe.md: -------------------------------------------------------------------------------- 1 | ## NEWM-Server 2 | 3 | 4 | ### Project Setup 5 | 6 | #### - Java 7 | We are using Java version 21 8 | 9 | #### - Docker Setup 10 | 1. Download docker image for your machine 11 | 2. Use default setting when installing docker https://docs.docker.com/desktop/release-notes/ 12 | 13 | #### - IJ Setup 14 | 1. Configure project settings 15 | ![Project Settings](/images/project-setting.png) 16 | 17 | 2. Configure module settings 18 | ![Project Settings](/images/modules-setting.png) 19 | 20 | 3. Configure gradle settings 21 | ![Project Settings](/images/gradle-settings.png) 22 | -------------------------------------------------------------------------------- /newm-server/images/gradle-settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectNEWM/newm-server/a96fc7499e5b2610bbb66cc1a305b26fa86ec2b0/newm-server/images/gradle-settings.png -------------------------------------------------------------------------------- /newm-server/images/modules-setting.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectNEWM/newm-server/a96fc7499e5b2610bbb66cc1a305b26fa86ec2b0/newm-server/images/modules-setting.png -------------------------------------------------------------------------------- /newm-server/images/project-setting.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectNEWM/newm-server/a96fc7499e5b2610bbb66cc1a305b26fa86ec2b0/newm-server/images/project-setting.png -------------------------------------------------------------------------------- /newm-server/initdb.d/init-user-db.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL 5 | CREATE USER ${DATABASE_USERNAME}; 6 | CREATE DATABASE ${DATABASE_NAME}; 7 | ALTER USER ${DATABASE_USERNAME} WITH PASSWORD '${DATABASE_PASSWORD}'; 8 | ALTER USER ${DATABASE_USERNAME} VALID UNTIL 'infinity'; 9 | ALTER DATABASE ${DATABASE_NAME} OWNER TO ${DATABASE_USERNAME}; 10 | EOSQL 11 | 12 | -------------------------------------------------------------------------------- /newm-server/src/integTest/kotlin/io/newm/server/HealthTest.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server 2 | 3 | import com.google.common.truth.Truth.assertThat 4 | import io.ktor.client.request.get 5 | import io.ktor.http.HttpStatusCode 6 | import kotlinx.coroutines.runBlocking 7 | import org.junit.jupiter.api.Test 8 | 9 | class HealthTest { 10 | @Test 11 | fun `healthcheck request`() = 12 | runBlocking { 13 | val response = TestContext.client.get("${TestContext.baseUrl}/healthz") 14 | assertThat(response.status).isEqualTo(HttpStatusCode.OK) 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /newm-server/src/integTest/kotlin/io/newm/server/StringExt.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server 2 | 3 | val charPool: List = ('a'..'z') + ('A'..'Z') + ('0'..'9') 4 | 5 | fun String.Companion.randomString(length: Int = 10) = List(length) { charPool.random() }.joinToString("") 6 | -------------------------------------------------------------------------------- /newm-server/src/integTest/resources/file_example.flac: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectNEWM/newm-server/a96fc7499e5b2610bbb66cc1a305b26fa86ec2b0/newm-server/src/integTest/resources/file_example.flac -------------------------------------------------------------------------------- /newm-server/src/integTest/resources/garage.conf: -------------------------------------------------------------------------------- 1 | newm { 2 | baseUrl = "https://garage.newm.io" 3 | baseUrl = ${?NEWM_BASEURL} 4 | 5 | // The email address you used to access newm 6 | email = ${NEWM_EMAIL} 7 | 8 | 9 | // The password you used to access newm 10 | password = ${NEWM_PASSWORD} 11 | } 12 | 13 | audio { 14 | happyPathFile = "src/integTest/resources/file_example.flac" 15 | } 16 | -------------------------------------------------------------------------------- /newm-server/src/integTest/resources/studio.conf: -------------------------------------------------------------------------------- 1 | newm { 2 | baseUrl = "https://studio.newm.io" 3 | baseUrl = ${?NEWM_BASEURL} 4 | 5 | // The email address you used to access newm 6 | email = ${NEWM_EMAIL} 7 | 8 | // The password you used to access newm" 9 | password = ${NEWM_PASSWORD} 10 | } 11 | 12 | audio { 13 | happyPathFile = "src/integTest/resources/file_example.flac" 14 | } 15 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/auth/AuthenticationInstall.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.auth 2 | 3 | import io.ktor.server.application.Application 4 | import io.ktor.server.application.install 5 | import io.ktor.server.auth.Authentication 6 | import io.newm.server.auth.jwt.configureJwt 7 | 8 | fun Application.installAuthentication() { 9 | install(Authentication) { 10 | configureJwt() 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/auth/AuthenticationKoinModule.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.auth 2 | 3 | import io.newm.server.auth.jwt.repo.JwtRepository 4 | import io.newm.server.auth.jwt.repo.JwtRepositoryImpl 5 | import io.newm.server.auth.oauth.repo.OAuthRepository 6 | import io.newm.server.auth.oauth.repo.OAuthRepositoryImpl 7 | import io.newm.server.auth.twofactor.repo.TwoFactorAuthRepository 8 | import io.newm.server.auth.twofactor.repo.TwoFactorAuthRepositoryImpl 9 | import org.koin.dsl.module 10 | 11 | val authKoinModule = 12 | module { 13 | single { TwoFactorAuthRepositoryImpl(get(), get()) } 14 | single { OAuthRepositoryImpl(get(), get()) } 15 | single { JwtRepositoryImpl(get()) } 16 | } 17 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/auth/jwt/JwtData.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.auth.jwt 2 | 3 | import kotlinx.serialization.Serializable 4 | 5 | @Serializable 6 | data class JwtData( 7 | val id: String, 8 | val issuer: String, 9 | val audience: String, 10 | val subject: String, 11 | val expiresAt: String 12 | ) 13 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/auth/jwt/JwtType.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.auth.jwt 2 | 3 | enum class JwtType { 4 | Access, 5 | Refresh 6 | } 7 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/auth/jwt/repo/JwtRepository.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.auth.jwt.repo 2 | 3 | import io.newm.server.auth.jwt.JwtType 4 | import io.newm.server.typealiases.UserId 5 | import java.util.UUID 6 | 7 | interface JwtRepository { 8 | suspend fun create( 9 | type: JwtType, 10 | userId: UserId, 11 | admin: Boolean 12 | ): String 13 | 14 | fun blackList(jwtId: UUID) 15 | 16 | fun isBlacklisted(jwtId: UUID): Boolean 17 | } 18 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/auth/oauth/model/OAuthLoginRequest.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.auth.oauth.model 2 | 3 | import kotlinx.serialization.Serializable 4 | 5 | @Serializable 6 | data class OAuthLoginRequest( 7 | val accessToken: String? = null, 8 | val idToken: String? = null, 9 | val code: String? = null, 10 | val redirectUri: String? = null 11 | ) { 12 | val oauthTokens: OAuthTokens? 13 | get() = if (accessToken != null || idToken != null) OAuthTokens(accessToken, idToken) else null 14 | } 15 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/auth/oauth/model/OAuthTokens.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.auth.oauth.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class OAuthTokens( 8 | @SerialName("access_token") 9 | val accessToken: String?, 10 | @SerialName("id_token") 11 | val idToken: String?, 12 | ) 13 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/auth/oauth/model/OAuthType.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.auth.oauth.model 2 | 3 | enum class OAuthType { 4 | Google, 5 | Facebook, 6 | LinkedIn, 7 | Apple 8 | } 9 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/auth/oauth/repo/OAuthRepository.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.auth.oauth.repo 2 | 3 | import io.newm.server.auth.oauth.model.OAuthTokens 4 | import io.newm.server.auth.oauth.model.OAuthType 5 | 6 | interface OAuthRepository { 7 | suspend fun getTokens( 8 | type: OAuthType, 9 | code: String, 10 | redirectUri: String? 11 | ): OAuthTokens 12 | } 13 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/auth/password/LoginRequest.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.auth.password 2 | 3 | import io.newm.shared.auth.Password 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class LoginRequest( 8 | val email: String, 9 | val password: Password 10 | ) 11 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/auth/password/LoginResponse.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.auth.password 2 | 3 | import io.newm.server.auth.jwt.JwtType 4 | import io.newm.server.auth.jwt.repo.JwtRepository 5 | import io.newm.server.typealiases.UserId 6 | import kotlinx.serialization.Serializable 7 | 8 | @Serializable 9 | data class LoginResponse( 10 | val accessToken: String, 11 | val refreshToken: String 12 | ) 13 | 14 | suspend fun JwtRepository.createLoginResponse( 15 | userId: UserId, 16 | admin: Boolean = false 17 | ) = LoginResponse( 18 | accessToken = create(JwtType.Access, userId, admin), 19 | refreshToken = create(JwtType.Refresh, userId, admin) 20 | ) 21 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/auth/twofactor/database/TwoFactorAuthTable.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.auth.twofactor.database 2 | 3 | import org.jetbrains.exposed.dao.id.LongIdTable 4 | import org.jetbrains.exposed.sql.Column 5 | import org.jetbrains.exposed.sql.javatime.datetime 6 | import java.time.LocalDateTime 7 | 8 | object TwoFactorAuthTable : LongIdTable(name = "two_factor_auth") { 9 | val email: Column = text("email") 10 | val codeHash: Column = text("code_hash") 11 | val expiresAt: Column = datetime("expires_at") 12 | } 13 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/auth/twofactor/repo/TwoFactorAuthRepository.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.auth.twofactor.repo 2 | 3 | interface TwoFactorAuthRepository { 4 | suspend fun sendCode( 5 | email: String, 6 | mustExists: Boolean, 7 | isMobileApp: Boolean 8 | ) 9 | 10 | suspend fun verifyCode( 11 | email: String, 12 | code: String 13 | ): Boolean 14 | } 15 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/aws/SqsMessageReceiver.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.aws 2 | 3 | import software.amazon.awssdk.services.sqs.model.Message 4 | 5 | interface SqsMessageReceiver { 6 | suspend fun onMessageReceived(message: Message) 7 | } 8 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/client/auth/model/TokenInfo.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.client.auth.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class TokenInfo( 8 | @SerialName("access_token") 9 | val accessToken: String, 10 | @SerialName("expires_in") 11 | val expiresIn: Int, 12 | @SerialName("token_type") val tokenType: String, 13 | ) 14 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/config/ConfigKoinModule.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.config 2 | 3 | import io.newm.server.config.repo.ConfigRepository 4 | import io.newm.server.config.repo.ConfigRepositoryImpl 5 | import org.koin.dsl.module 6 | 7 | val configKoinModule = 8 | module { 9 | single { ConfigRepositoryImpl() } 10 | } 11 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/config/database/ConfigEntity.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.config.database 2 | 3 | import org.jetbrains.exposed.dao.Entity 4 | import org.jetbrains.exposed.dao.EntityClass 5 | import org.jetbrains.exposed.dao.id.EntityID 6 | 7 | class ConfigEntity( 8 | id: EntityID 9 | ) : Entity(id) { 10 | var value: String by ConfigTable.value 11 | 12 | companion object : EntityClass(ConfigTable) 13 | } 14 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/config/database/ConfigTable.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.config.database 2 | 3 | import org.jetbrains.exposed.dao.id.EntityID 4 | import org.jetbrains.exposed.dao.id.IdTable 5 | import org.jetbrains.exposed.sql.Column 6 | 7 | object ConfigTable : IdTable(name = "config") { 8 | override val id: Column> = text("id").entityId() 9 | val value: Column = text("value") 10 | } 11 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/content/ContentNegotiationInstall.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.content 2 | 3 | import io.ktor.serialization.kotlinx.json.json 4 | import io.ktor.server.application.Application 5 | import io.ktor.server.application.install 6 | import io.ktor.server.plugins.contentnegotiation.ContentNegotiation 7 | import kotlinx.serialization.json.Json 8 | import org.koin.ktor.ext.inject 9 | 10 | fun Application.installContentNegotiation() { 11 | val json: Json by inject() 12 | install(ContentNegotiation) { 13 | json(json = json) 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/curator/support/FileEnsembleProvider.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.curator.support 2 | 3 | import org.apache.curator.ensemble.EnsembleProvider 4 | import java.io.File 5 | 6 | class FileEnsembleProvider( 7 | private val filePath: String 8 | ) : EnsembleProvider { 9 | override fun close() {} 10 | 11 | override fun start() {} 12 | 13 | override fun getConnectionString(): String = File(filePath).readText().trim() 14 | 15 | override fun setConnectionString(value: String) {} 16 | 17 | override fun updateServerListEnabled(): Boolean = false 18 | } 19 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/database/migration/V11__SongsUpdates.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.database.migration 2 | 3 | import org.flywaydb.core.api.migration.BaseJavaMigration 4 | import org.flywaydb.core.api.migration.Context 5 | import org.jetbrains.exposed.sql.transactions.transaction 6 | 7 | @Suppress("unused") 8 | class V11__SongsUpdates : BaseJavaMigration() { 9 | override fun migrate(context: Context?) { 10 | transaction { 11 | exec( 12 | "ALTER TABLE songs ADD COLUMN IF NOT EXISTS payment_key_id uuid CONSTRAINT fk_songs_payment_key_id__id REFERENCES keys (id) ON DELETE NO ACTION ON UPDATE RESTRICT" 13 | ) 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/database/migration/V13__CreateConfig.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.database.migration 2 | 3 | import org.flywaydb.core.api.migration.BaseJavaMigration 4 | import org.flywaydb.core.api.migration.Context 5 | import org.jetbrains.exposed.sql.transactions.transaction 6 | 7 | @Suppress("unused") 8 | class V13__CreateConfig : BaseJavaMigration() { 9 | override fun migrate(context: Context?) { 10 | transaction { 11 | execInBatch( 12 | listOf( 13 | "CREATE TABLE IF NOT EXISTS config (id text PRIMARY KEY, value TEXT NOT NULL)", 14 | "INSERT INTO config VALUES ('mint.price','6000000') ON CONFLICT(id) DO NOTHING" 15 | ) 16 | ) 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/database/migration/V17__CollaborationsUpdates.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.database.migration 2 | 3 | import org.flywaydb.core.api.migration.BaseJavaMigration 4 | import org.flywaydb.core.api.migration.Context 5 | import org.jetbrains.exposed.sql.transactions.transaction 6 | 7 | @Suppress("unused") 8 | class V17__CollaborationsUpdates : BaseJavaMigration() { 9 | override fun migrate(context: Context?) { 10 | transaction { 11 | exec("ALTER TABLE collaborations ADD COLUMN IF NOT EXISTS credited boolean NOT NULL DEFAULT false") 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/database/migration/V19__CollaborationsUpdates.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.database.migration 2 | 3 | import org.flywaydb.core.api.migration.BaseJavaMigration 4 | import org.flywaydb.core.api.migration.Context 5 | import org.jetbrains.exposed.sql.transactions.transaction 6 | 7 | @Suppress("unused") 8 | class V19__CollaborationsUpdates : BaseJavaMigration() { 9 | override fun migrate(context: Context?) { 10 | transaction { 11 | exec( 12 | """ 13 | ALTER TABLE collaborations 14 | DROP COLUMN IF EXISTS accepted, 15 | ADD COLUMN IF NOT EXISTS status int NOT NULL DEFAULT 0 16 | """.trimIndent() 17 | ) 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/database/migration/V20__SongsUpdates.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.database.migration 2 | 3 | import org.flywaydb.core.api.migration.BaseJavaMigration 4 | import org.flywaydb.core.api.migration.Context 5 | import org.jetbrains.exposed.sql.transactions.transaction 6 | 7 | @Suppress("unused") 8 | class V20__SongsUpdates : BaseJavaMigration() { 9 | override fun migrate(context: Context?) { 10 | transaction { 11 | exec("ALTER TABLE songs ADD COLUMN IF NOT EXISTS original_audio_url TEXT") 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/database/migration/V21__CollaborationsUpdates.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.database.migration 2 | 3 | import org.flywaydb.core.api.migration.BaseJavaMigration 4 | import org.flywaydb.core.api.migration.Context 5 | import org.jetbrains.exposed.sql.transactions.transaction 6 | 7 | @Suppress("unused") 8 | class V21__CollaborationsUpdates : BaseJavaMigration() { 9 | override fun migrate(context: Context?) { 10 | transaction { 11 | exec("ALTER TABLE collaborations ADD COLUMN IF NOT EXISTS featured boolean NOT NULL DEFAULT false") 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/database/migration/V23__ConfigUpdates.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.database.migration 2 | 3 | import org.flywaydb.core.api.migration.BaseJavaMigration 4 | import org.flywaydb.core.api.migration.Context 5 | import org.jetbrains.exposed.sql.transactions.transaction 6 | 7 | @Suppress("unused") 8 | class V23__ConfigUpdates : BaseJavaMigration() { 9 | override fun migrate(context: Context?) { 10 | transaction { 11 | execInBatch( 12 | listOf( 13 | "INSERT INTO config VALUES ('scheduler.evearaSync','0 0 0 * * ?') ON CONFLICT(id) DO NOTHING" 14 | ) 15 | ) 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/database/migration/V26__SongsUpdates.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.database.migration 2 | 3 | import org.flywaydb.core.api.migration.BaseJavaMigration 4 | import org.flywaydb.core.api.migration.Context 5 | import org.jetbrains.exposed.sql.transactions.transaction 6 | 7 | @Suppress("unused") 8 | class V26__SongsUpdates : BaseJavaMigration() { 9 | override fun migrate(context: Context?) { 10 | transaction { 11 | exec("ALTER TABLE songs RENAME COLUMN ipi TO ipis") 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/database/migration/V28__UsersUpdates.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.database.migration 2 | 3 | import org.flywaydb.core.api.migration.BaseJavaMigration 4 | import org.flywaydb.core.api.migration.Context 5 | import org.jetbrains.exposed.sql.transactions.transaction 6 | 7 | @Suppress("unused") 8 | class V28__UsersUpdates : BaseJavaMigration() { 9 | override fun migrate(context: Context?) { 10 | transaction { 11 | execInBatch( 12 | listOf( 13 | "ALTER TABLE users ALTER COLUMN distribution_user_id TYPE TEXT" 14 | ) 15 | ) 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/database/migration/V30__SongsUpdates.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.database.migration 2 | 3 | import org.flywaydb.core.api.migration.BaseJavaMigration 4 | import org.flywaydb.core.api.migration.Context 5 | import org.jetbrains.exposed.sql.transactions.transaction 6 | 7 | @Suppress("unused") 8 | class V30__SongsUpdates : BaseJavaMigration() { 9 | override fun migrate(context: Context?) { 10 | transaction { 11 | exec("ALTER TABLE songs ADD COLUMN IF NOT EXISTS mint_cost_lovelace BIGINT") 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/database/migration/V31__ConfigUpdates.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.database.migration 2 | 3 | import org.flywaydb.core.api.migration.BaseJavaMigration 4 | import org.flywaydb.core.api.migration.Context 5 | import org.jetbrains.exposed.sql.transactions.transaction 6 | 7 | @Suppress("unused") 8 | class V31__ConfigUpdates : BaseJavaMigration() { 9 | override fun migrate(context: Context?) { 10 | transaction { 11 | execInBatch( 12 | listOf( 13 | // default 24 hours 14 | "INSERT INTO config VALUES ('eveara.statusCheckMinutes','1440') ON CONFLICT(id) DO NOTHING", 15 | ) 16 | ) 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/database/migration/V32__SongsUpdates.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.database.migration 2 | 3 | import org.flywaydb.core.api.migration.BaseJavaMigration 4 | import org.flywaydb.core.api.migration.Context 5 | import org.jetbrains.exposed.sql.transactions.transaction 6 | 7 | @Suppress("unused") 8 | class V32__SongsUpdates : BaseJavaMigration() { 9 | override fun migrate(context: Context?) { 10 | transaction { 11 | exec("ALTER TABLE songs ADD COLUMN IF NOT EXISTS force_distributed BOOLEAN") 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/database/migration/V35__SongsUpdates.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.database.migration 2 | 3 | import org.flywaydb.core.api.migration.BaseJavaMigration 4 | import org.flywaydb.core.api.migration.Context 5 | import org.jetbrains.exposed.sql.transactions.transaction 6 | 7 | @Suppress("unused") 8 | class V35__SongsUpdates : BaseJavaMigration() { 9 | override fun migrate(context: Context?) { 10 | transaction { 11 | execInBatch( 12 | listOf( 13 | "ALTER TABLE songs ADD COLUMN IF NOT EXISTS minting_tx_id TEXT", 14 | ) 15 | ) 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/database/migration/V36__SongsUpdates.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.database.migration 2 | 3 | import org.flywaydb.core.api.migration.BaseJavaMigration 4 | import org.flywaydb.core.api.migration.Context 5 | import org.jetbrains.exposed.sql.transactions.transaction 6 | 7 | @Suppress("unused") 8 | class V36__SongsUpdates : BaseJavaMigration() { 9 | override fun migrate(context: Context?) { 10 | transaction { 11 | exec("ALTER TABLE songs ADD COLUMN IF NOT EXISTS archived BOOLEAN NOT NULL DEFAULT false") 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/database/migration/V38__SongsUpdates.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.database.migration 2 | 3 | import org.flywaydb.core.api.migration.BaseJavaMigration 4 | import org.flywaydb.core.api.migration.Context 5 | import org.jetbrains.exposed.sql.transactions.transaction 6 | 7 | @Suppress("unused") 8 | class V38__SongsUpdates : BaseJavaMigration() { 9 | override fun migrate(context: Context?) { 10 | transaction { 11 | exec("ALTER TABLE songs ADD COLUMN IF NOT EXISTS error_message TEXT") 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/database/migration/V39__ConfigUpdates.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.database.migration 2 | 3 | import org.flywaydb.core.api.migration.BaseJavaMigration 4 | import org.flywaydb.core.api.migration.Context 5 | import org.jetbrains.exposed.sql.transactions.transaction 6 | 7 | @Suppress("unused") 8 | class V39__ConfigUpdates : BaseJavaMigration() { 9 | override fun migrate(context: Context?) { 10 | transaction { 11 | execInBatch( 12 | listOf( 13 | // default $14.99 14 | "INSERT INTO config VALUES ('distribution.price.usd','14990000') ON CONFLICT(id) DO NOTHING", 15 | ) 16 | ) 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/database/migration/V3__SongsUpdates.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.database.migration 2 | 3 | import org.flywaydb.core.api.migration.BaseJavaMigration 4 | import org.flywaydb.core.api.migration.Context 5 | import org.jetbrains.exposed.sql.transactions.transaction 6 | 7 | @Suppress("unused") 8 | class V3__SongsUpdates : BaseJavaMigration() { 9 | override fun migrate(context: Context?) { 10 | transaction { 11 | exec( 12 | """ 13 | ALTER TABLE songs 14 | ADD COLUMN duration int 15 | """.trimIndent() 16 | ) 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/database/migration/V40__SongsUpdates.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.database.migration 2 | 3 | import org.flywaydb.core.api.migration.BaseJavaMigration 4 | import org.flywaydb.core.api.migration.Context 5 | import org.jetbrains.exposed.sql.transactions.transaction 6 | 7 | @Suppress("unused") 8 | class V40__SongsUpdates : BaseJavaMigration() { 9 | override fun migrate(context: Context?) { 10 | transaction { 11 | exec("ALTER TABLE songs ADD COLUMN IF NOT EXISTS cover_remix_sample BOOLEAN NOT NULL DEFAULT false") 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/database/migration/V42__UsersUpdates.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.database.migration 2 | 3 | import org.flywaydb.core.api.migration.BaseJavaMigration 4 | import org.flywaydb.core.api.migration.Context 5 | import org.jetbrains.exposed.sql.transactions.transaction 6 | 7 | @Suppress("unused") 8 | class V42__UsersUpdates : BaseJavaMigration() { 9 | override fun migrate(context: Context?) { 10 | transaction { 11 | exec("ALTER TABLE users ADD COLUMN IF NOT EXISTS dsp_plan_subscribed BOOLEAN NOT NULL DEFAULT false") 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/database/migration/V43__UsersUpdates.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.database.migration 2 | 3 | import org.flywaydb.core.api.migration.BaseJavaMigration 4 | import org.flywaydb.core.api.migration.Context 5 | import org.jetbrains.exposed.sql.transactions.transaction 6 | 7 | @Suppress("unused") 8 | class V43__UsersUpdates : BaseJavaMigration() { 9 | override fun migrate(context: Context?) { 10 | transaction { 11 | exec( 12 | """ 13 | ALTER TABLE users 14 | ADD COLUMN IF NOT EXISTS isni text, 15 | ADD COLUMN IF NOT EXISTS ipi text 16 | """.trimIndent() 17 | ) 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/database/migration/V46__SongsUpdates.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.database.migration 2 | 3 | import org.flywaydb.core.api.migration.BaseJavaMigration 4 | import org.flywaydb.core.api.migration.Context 5 | import org.jetbrains.exposed.sql.transactions.transaction 6 | 7 | @Suppress("unused") 8 | class V46__SongsUpdates : BaseJavaMigration() { 9 | override fun migrate(context: Context?) { 10 | transaction { 11 | execInBatch( 12 | listOf( 13 | "ALTER TABLE songs ADD COLUMN IF NOT EXISTS instrumental BOOLEAN NOT NULL DEFAULT FALSE", 14 | "UPDATE songs SET instrumental = TRUE WHERE 'Instrumental' = ANY(genres)", 15 | ) 16 | ) 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/database/migration/V47__CollaborationsUpdates.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.database.migration 2 | 3 | import org.flywaydb.core.api.migration.BaseJavaMigration 4 | import org.flywaydb.core.api.migration.Context 5 | import org.jetbrains.exposed.sql.transactions.transaction 6 | 7 | @Suppress("unused") 8 | class V47__CollaborationsUpdates : BaseJavaMigration() { 9 | override fun migrate(context: Context?) { 10 | transaction { 11 | exec("ALTER TABLE collaborations ADD COLUMN IF NOT EXISTS distribution_participant_id BIGINT") 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/database/migration/V51__WalletConnectionsUpdates.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.database.migration 2 | 3 | import org.flywaydb.core.api.migration.BaseJavaMigration 4 | import org.flywaydb.core.api.migration.Context 5 | import org.jetbrains.exposed.sql.transactions.transaction 6 | 7 | @Suppress("unused") 8 | class V51__WalletConnectionsUpdates : BaseJavaMigration() { 9 | override fun migrate(context: Context?) { 10 | transaction { 11 | exec("ALTER TABLE wallet_connection_challenges DROP COLUMN IF EXISTS payload") 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/database/migration/V55__ConfigUpdates.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.database.migration 2 | 3 | import org.flywaydb.core.api.migration.BaseJavaMigration 4 | import org.flywaydb.core.api.migration.Context 5 | import org.jetbrains.exposed.sql.transactions.transaction 6 | 7 | @Suppress("unused") 8 | class V55__ConfigUpdates : BaseJavaMigration() { 9 | override fun migrate(context: Context?) { 10 | transaction { 11 | exec( 12 | // Check album status every 720(minutes) X 30(days) = 21600 minutes 13 | "INSERT INTO config VALUES ('eveara.statusCheckDeclinedMaxRefire','21600') ON CONFLICT(id) DO NOTHING", 14 | ) 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/database/migration/V58__ReleasesUpdates.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.database.migration 2 | 3 | import org.flywaydb.core.api.migration.BaseJavaMigration 4 | import org.flywaydb.core.api.migration.Context 5 | import org.jetbrains.exposed.sql.transactions.transaction 6 | 7 | @Suppress("unused") 8 | class V58__ReleasesUpdates : BaseJavaMigration() { 9 | override fun migrate(context: Context?) { 10 | transaction { 11 | exec( 12 | """ 13 | ALTER TABLE releases 14 | ADD COLUMN IF NOT EXISTS pre_save_page text 15 | """.trimIndent() 16 | ) 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/database/migration/V60__EarningsUpdates.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.database.migration 2 | 3 | import org.flywaydb.core.api.migration.BaseJavaMigration 4 | import org.flywaydb.core.api.migration.Context 5 | import org.jetbrains.exposed.sql.transactions.transaction 6 | 7 | @Suppress("unused") 8 | class V60__EarningsUpdates : BaseJavaMigration() { 9 | override fun migrate(context: Context?) { 10 | transaction { 11 | // add error_message column to claim_orders table 12 | exec("ALTER TABLE claim_orders ADD COLUMN IF NOT EXISTS error_message TEXT") 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/database/migration/V62__ConfigUpdates.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.database.migration 2 | 3 | import org.flywaydb.core.api.migration.BaseJavaMigration 4 | import org.flywaydb.core.api.migration.Context 5 | import org.jetbrains.exposed.sql.transactions.transaction 6 | 7 | @Suppress("unused") 8 | class V62__ConfigUpdates : BaseJavaMigration() { 9 | override fun migrate(context: Context?) { 10 | transaction { 11 | exec( 12 | // Add NEWM album id 13 | "INSERT INTO config VALUES ('newm.playlist.id','4I1cdKzkEzNotxwMPqtM6U') ON CONFLICT(id) DO NOTHING", 14 | ) 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/database/migration/V63__UsersUpdates.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.database.migration 2 | 3 | import org.flywaydb.core.api.migration.BaseJavaMigration 4 | import org.flywaydb.core.api.migration.Context 5 | import org.jetbrains.exposed.sql.transactions.transaction 6 | 7 | @Suppress("unused") 8 | class V63__UsersUpdates : BaseJavaMigration() { 9 | override fun migrate(context: Context?) { 10 | transaction { 11 | exec("ALTER TABLE users ADD COLUMN IF NOT EXISTS signup_platform integer NOT NULL DEFAULT 0") 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/database/migration/V65__JwtsDrop.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.database.migration 2 | 3 | import org.flywaydb.core.api.migration.BaseJavaMigration 4 | import org.flywaydb.core.api.migration.Context 5 | import org.jetbrains.exposed.sql.transactions.transaction 6 | 7 | @Suppress("unused") 8 | class V65__JwtsDrop : BaseJavaMigration() { 9 | override fun migrate(context: Context?) { 10 | transaction { 11 | exec("DROP TABLE IF EXISTS jwts") 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/database/migration/V73__UsersUpdates.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.database.migration 2 | 3 | import org.flywaydb.core.api.migration.BaseJavaMigration 4 | import org.flywaydb.core.api.migration.Context 5 | import org.jetbrains.exposed.sql.transactions.transaction 6 | 7 | @Suppress("unused") 8 | class V73__UsersUpdates : BaseJavaMigration() { 9 | override fun migrate(context: Context?) { 10 | transaction { 11 | execInBatch( 12 | listOf( 13 | """ 14 | ALTER TABLE users ALTER COLUMN verification_status SET DEFAULT 0 15 | """.trimIndent() 16 | ) 17 | ) 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/database/migration/V74__UsersUpdates.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.database.migration 2 | 3 | import org.flywaydb.core.api.migration.BaseJavaMigration 4 | import org.flywaydb.core.api.migration.Context 5 | import org.jetbrains.exposed.sql.transactions.transaction 6 | 7 | @Suppress("unused") 8 | class V74__UsersUpdates : BaseJavaMigration() { 9 | override fun migrate(context: Context?) { 10 | transaction { 11 | exec( 12 | """ 13 | ALTER TABLE users 14 | ADD COLUMN IF NOT EXISTS referral_status int NOT NULL DEFAULT 0, 15 | ADD COLUMN IF NOT EXISTS referral_code TEXT 16 | """.trimIndent() 17 | ) 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/database/migration/V77__ConfigUpdates.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.database.migration 2 | 3 | import org.flywaydb.core.api.migration.BaseJavaMigration 4 | import org.flywaydb.core.api.migration.Context 5 | import org.jetbrains.exposed.sql.transactions.transaction 6 | 7 | @Suppress("unused") 8 | class V77__ConfigUpdates : BaseJavaMigration() { 9 | override fun migrate(context: Context?) { 10 | transaction { 11 | exec("INSERT INTO config VALUES ('referralHero.enabled','false') ON CONFLICT(id) DO NOTHING") 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/database/migration/V8__SongsUpdates.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.database.migration 2 | 3 | import org.flywaydb.core.api.migration.BaseJavaMigration 4 | import org.flywaydb.core.api.migration.Context 5 | import org.jetbrains.exposed.sql.transactions.transaction 6 | 7 | @Suppress("unused") 8 | class V8__SongsUpdates : BaseJavaMigration() { 9 | override fun migrate(context: Context?) { 10 | transaction { 11 | exec("ALTER TABLE songs ADD COLUMN IF NOT EXISTS moods TEXT ARRAY") 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/arweave/ArweaveKoinModule.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.arweave 2 | 3 | import io.newm.server.features.arweave.repo.ArweaveRepository 4 | import io.newm.server.features.arweave.repo.ArweaveRepositoryImpl 5 | import org.koin.dsl.module 6 | 7 | val arweaveKoinModule = 8 | module { 9 | single { ArweaveRepositoryImpl(get(), get()) } 10 | } 11 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/arweave/model/UploadResponse.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.arweave.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class UploadResponse( 8 | @SerialName("id") 9 | val id: String, 10 | @SerialName("timestamp") 11 | val timestamp: Long, 12 | ) 13 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/arweave/model/WeaveFile.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.arweave.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class WeaveFile( 8 | @SerialName("url") 9 | val url: String, 10 | @SerialName("contentType") 11 | val contentType: String, 12 | ) 13 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/arweave/model/WeaveProps.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.arweave.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class WeaveProps( 8 | @SerialName("arweaveWalletJson") 9 | val arweaveWalletJson: String, 10 | @SerialName("files") 11 | val files: List, 12 | @SerialName("checkAndFund") 13 | val checkAndFund: Boolean, 14 | ) 15 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/arweave/model/WeaveRequest.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.arweave.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class WeaveRequest( 8 | @SerialName("body") 9 | val body: String, 10 | ) 11 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/arweave/model/WeaveResponse.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.arweave.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class WeaveResponse( 8 | @SerialName("statusCode") 9 | val statusCode: Int, 10 | @SerialName("body") 11 | val body: String, 12 | ) 13 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/arweave/model/WeaveResponseItem.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.arweave.model 2 | 3 | import kotlinx.serialization.Contextual 4 | import kotlinx.serialization.SerialName 5 | import kotlinx.serialization.Serializable 6 | 7 | @Serializable 8 | data class WeaveResponseItem( 9 | @SerialName("url") 10 | val url: String, 11 | @SerialName("contentType") 12 | val contentType: String, 13 | @SerialName("id") 14 | val id: String? = null, 15 | @SerialName("error") 16 | val error: Map? = null, 17 | ) 18 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/arweave/repo/ArweaveRepository.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.arweave.repo 2 | 3 | import io.newm.server.features.song.model.Song 4 | import java.math.BigDecimal 5 | 6 | interface ArweaveRepository { 7 | suspend fun getWalletAddress(): String 8 | 9 | suspend fun getWalletARBalance(): BigDecimal 10 | 11 | suspend fun uploadSongAssets(song: Song) 12 | } 13 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/cardano/database/ScriptAddressWhitelistEntity.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.cardano.database 2 | 3 | import java.util.UUID 4 | import org.jetbrains.exposed.dao.UUIDEntity 5 | import org.jetbrains.exposed.dao.UUIDEntityClass 6 | import org.jetbrains.exposed.dao.id.EntityID 7 | 8 | class ScriptAddressWhitelistEntity( 9 | id: EntityID 10 | ) : UUIDEntity(id) { 11 | var scriptAddress: String by ScriptAddressWhitelistTable.scriptAddress 12 | 13 | companion object : UUIDEntityClass(ScriptAddressWhitelistTable) 14 | } 15 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/cardano/database/ScriptAddressWhitelistTable.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.cardano.database 2 | 3 | import org.jetbrains.exposed.dao.id.UUIDTable 4 | import org.jetbrains.exposed.sql.Column 5 | 6 | object ScriptAddressWhitelistTable : UUIDTable(name = "script_address_whitelist") { 7 | // scriptAddress that is allowed to pull earnings. We prevent anything sitting in some smart contracts from pulling 8 | // earnings so tokens are never perma-locked. This is a whitelist of script addresses that are allowed to pull earnings 9 | // such as multi-sig wallets. 10 | val scriptAddress: Column = text("script_address") 11 | } 12 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/cardano/model/CliKey.kt: -------------------------------------------------------------------------------- 1 | package com.firehose.model 2 | 3 | import kotlinx.serialization.Serializable 4 | 5 | @Serializable 6 | data class CliKey( 7 | val type: String, 8 | val description: String, 9 | val cborHex: String 10 | ) 11 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/cardano/model/CliKeyPair.kt: -------------------------------------------------------------------------------- 1 | package com.firehose.model 2 | 3 | import kotlinx.serialization.Serializable 4 | 5 | @Serializable 6 | data class CliKeyPair( 7 | val name: String, 8 | val vkey: CliKey, 9 | val skey: CliKey? = null, 10 | ) 11 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/cardano/model/EncryptionRequest.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.cardano.model 2 | 3 | import kotlinx.serialization.Serializable 4 | 5 | @Serializable 6 | data class EncryptionRequest( 7 | // The salt. Should be random hex. more than 8 bytes 8 | val s: String, 9 | // The spending password used for a password-based key generating function 10 | val password: String, 11 | ) 12 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/cardano/model/GetWalletSongsResponse.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.cardano.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class GetWalletSongsResponse( 8 | @SerialName("songs") 9 | val songs: List, 10 | @SerialName("total") 11 | val total: Long, 12 | @SerialName("offset") 13 | val offset: Int, 14 | @SerialName("limit") 15 | val limit: Int, 16 | ) 17 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/cardano/model/KeyFilters.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.cardano.model 2 | 3 | import java.time.LocalDateTime 4 | import java.util.UUID 5 | 6 | data class KeyFilters( 7 | val olderThan: LocalDateTime?, 8 | val newerThan: LocalDateTime?, 9 | val ids: List?, 10 | val address: String?, 11 | val scriptAddress: String?, 12 | ) 13 | 14 | // val ApplicationCall.keyFilters: KeyFilters 15 | // get() = KeyFilters(olderThan, newerThan, ids, address, scriptAddress) 16 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/cardano/model/NFTSong.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.cardano.model 2 | 3 | import kotlinx.serialization.Contextual 4 | import kotlinx.serialization.Serializable 5 | import java.util.UUID 6 | 7 | @Serializable 8 | data class NFTSong( 9 | @Contextual 10 | val id: UUID, 11 | val fingerprint: String, 12 | val policyId: String, 13 | val assetName: String, 14 | val isStreamToken: Boolean, 15 | val amount: Long, 16 | val title: String, 17 | val imageUrl: String, 18 | val audioUrl: String, 19 | val duration: Long, 20 | val artists: List, 21 | val genres: List, 22 | val moods: List 23 | ) 24 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/cardano/model/QueryPriceResponse.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.cardano.model 2 | 3 | import kotlinx.serialization.Serializable 4 | 5 | @Serializable 6 | data class QueryPriceResponse( 7 | val usdPrice: Long 8 | ) 9 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/cardano/model/ScriptAddressWhitelistRequest.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.cardano.model 2 | 3 | import kotlinx.serialization.Serializable 4 | 5 | @Serializable 6 | data class ScriptAddressWhitelistRequest( 7 | val scriptAddress: String, 8 | ) 9 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/cardano/model/SubmitTransactionRequest.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.cardano.model 2 | 3 | import io.newm.server.typealiases.SongId 4 | import kotlinx.serialization.Contextual 5 | import kotlinx.serialization.Serializable 6 | 7 | @Serializable 8 | data class SubmitTransactionRequest( 9 | @Contextual 10 | val songId: SongId, 11 | val cborHex: String 12 | ) 13 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/cardano/model/SubmitTransactionResponse.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.cardano.model 2 | 3 | import kotlinx.serialization.Serializable 4 | 5 | @Serializable 6 | data class SubmitTransactionResponse( 7 | val txId: String? = null, 8 | val result: String? = null, 9 | ) 10 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/cardano/model/SubmitTxRequest.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.cardano.model 2 | 3 | import kotlinx.serialization.Serializable 4 | 5 | @Serializable 6 | data class SubmitTxRequest( 7 | val cborHex: String 8 | ) 9 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/cardano/model/WalletSong.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.cardano.model 2 | 3 | import io.newm.server.features.song.model.Song 4 | import kotlinx.serialization.SerialName 5 | import kotlinx.serialization.Serializable 6 | 7 | @Serializable 8 | data class WalletSong( 9 | @SerialName("song") 10 | val song: Song, 11 | @SerialName("token_amount") 12 | val tokenAmount: Long, 13 | ) 14 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/cloudinary/CloudinaryKoinModule.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.cloudinary 2 | 3 | import com.cloudinary.Cloudinary 4 | import io.ktor.server.application.ApplicationEnvironment 5 | import io.newm.shared.ktx.getConfigString 6 | import org.koin.dsl.module 7 | 8 | val cloudinaryKoinModule = 9 | module { 10 | single { Cloudinary(get().getConfigString("cloudinary.url")) } 11 | } 12 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/cloudinary/model/CloudinarySignResponse.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.cloudinary.model 2 | 3 | import kotlinx.serialization.Serializable 4 | 5 | @Serializable 6 | data class CloudinarySignResponse( 7 | val signature: String, 8 | val timestamp: Long, 9 | val cloudName: String, 10 | val apiKey: String 11 | ) 12 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/collaboration/CollaborationKoinModule.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.collaboration 2 | 3 | import io.newm.server.features.collaboration.repo.CollaborationRepository 4 | import io.newm.server.features.collaboration.repo.CollaborationRepositoryImpl 5 | import org.koin.dsl.module 6 | 7 | val collaborationKoinModule = 8 | module { 9 | single { CollaborationRepositoryImpl(get(), get()) } 10 | } 11 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/collaboration/model/CollaborationIdBody.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.collaboration.model 2 | 3 | import kotlinx.serialization.Contextual 4 | import kotlinx.serialization.Serializable 5 | import java.util.UUID 6 | 7 | @Serializable 8 | data class CollaborationIdBody( 9 | @Contextual 10 | val collaborationId: UUID 11 | ) 12 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/collaboration/model/CollaborationReply.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.collaboration.model 2 | 3 | import kotlinx.serialization.Serializable 4 | 5 | @Serializable 6 | data class CollaborationReply( 7 | val accepted: Boolean 8 | ) 9 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/collaboration/model/CollaborationStatus.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.collaboration.model 2 | 3 | enum class CollaborationStatus { 4 | Editing, // Editing BEFORE artist accepts the stream token agreement 5 | Waiting, // Waiting collaborator response AFTER artist accepts the stream token agreement 6 | Accepted, // Accepted by collaborator 7 | Rejected, // Rejected by collaborator 8 | } 9 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/collaboration/model/Collaborator.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.collaboration.model 2 | 3 | import io.newm.server.features.user.model.User 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class Collaborator( 8 | val email: String? = null, 9 | val songCount: Long? = null, 10 | val user: User? = null 11 | ) 12 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/distribution/DistributionKoinModule.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.distribution 2 | 3 | import io.newm.server.features.distribution.eveara.EvearaDistributionRepositoryImpl 4 | import org.koin.dsl.module 5 | 6 | val distributionKoinModule = 7 | module { 8 | single { EvearaDistributionRepositoryImpl(get(), get()) } 9 | } 10 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/distribution/model/AddAlbumResponse.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.distribution.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class AddAlbumResponse( 8 | @SerialName("message") 9 | val message: String, 10 | @SerialName("success") 11 | val success: Boolean, 12 | @SerialName("release_id") 13 | val releaseId: Long 14 | ) 15 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/distribution/model/AddArtistRequest.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.distribution.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class AddArtistRequest( 8 | @SerialName("uuid") 9 | val uuid: String, 10 | @SerialName("name") 11 | val name: String, 12 | @SerialName("country") 13 | val country: String, 14 | @SerialName("outlets_profile") 15 | val outletProfiles: List? = null 16 | ) 17 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/distribution/model/AddArtistResponse.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.distribution.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class AddArtistResponse( 8 | @SerialName("message") 9 | val message: String, 10 | @SerialName("success") 11 | val success: Boolean, 12 | @SerialName("artist_id") 13 | val artistId: Long, 14 | ) 15 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/distribution/model/AddParticipantRequest.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.distribution.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class AddParticipantRequest( 8 | @SerialName("uuid") 9 | val uuid: String, 10 | @SerialName("name") 11 | val name: String, 12 | @SerialName("isni") 13 | val isni: String?, 14 | @SerialName("ipn") 15 | val ipn: String?, 16 | ) 17 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/distribution/model/AddParticipantResponse.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.distribution.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class AddParticipantResponse( 8 | @SerialName("message") 9 | val message: String, 10 | @SerialName("success") 11 | val success: Boolean, 12 | @SerialName("participant_id") 13 | val participantId: Long 14 | ) 15 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/distribution/model/AddTrackResponse.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.distribution.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class AddTrackResponse( 8 | @SerialName("message") 9 | val message: String, 10 | @SerialName("success") 11 | val success: Boolean, 12 | @SerialName("track_id") 13 | val trackId: Long, 14 | ) 15 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/distribution/model/AddUserLabelRequest.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.distribution.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class AddUserLabelRequest( 8 | @SerialName("uuid") 9 | val uuid: String, 10 | @SerialName("name") 11 | val name: String 12 | ) 13 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/distribution/model/AddUserLabelResponse.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.distribution.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class AddUserLabelResponse( 8 | @SerialName("message") 9 | val message: String, 10 | @SerialName("success") 11 | val success: Boolean, 12 | @SerialName("label_id") 13 | val labelId: Long, 14 | ) 15 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/distribution/model/AddUserRequest.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.distribution.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class AddUserRequest( 8 | @SerialName("first_name") 9 | val firstName: String, 10 | @SerialName("sur_name") 11 | val lastName: String, 12 | @SerialName("email") 13 | val email: String, 14 | ) 15 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/distribution/model/AddUserResponse.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.distribution.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class AddUserResponse( 8 | @SerialName("message") 9 | val message: String, 10 | @SerialName("success") 11 | val success: Boolean, 12 | @SerialName("uuid") 13 | val uuid: String, 14 | ) 15 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/distribution/model/AddUserSubscriptionRequest.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.distribution.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class AddUserSubscriptionRequest( 8 | @SerialName("uuid") 9 | val uuid: String, 10 | @SerialName("subscriptions") 11 | val subscriptions: List 12 | ) 13 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/distribution/model/AddUserSubscriptionResponse.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.distribution.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class AddUserSubscriptionResponse( 8 | @SerialName("message") 9 | val message: String, 10 | @SerialName("success") 11 | val success: Boolean, 12 | @SerialName("data") 13 | val subscriptions: List 14 | ) 15 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/distribution/model/AlbumPrice.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.distribution.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class AlbumPrice( 8 | @SerialName("price") 9 | val price: Double, 10 | @SerialName("price_id") 11 | val priceId: Long, 12 | ) 13 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/distribution/model/AlbumStatus.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.distribution.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class AlbumStatus( 8 | @SerialName("status_code") 9 | val statusCode: Int, 10 | @SerialName("status_name") 11 | val statusName: String 12 | ) 13 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/distribution/model/Artist.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.distribution.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | import kotlinx.serialization.json.JsonNames 6 | 7 | @Serializable 8 | data class Artist( 9 | @SerialName("id") 10 | @JsonNames("id", "artist_id") 11 | val id: Long, 12 | @SerialName("name") 13 | @JsonNames("name", "artist_name") 14 | val name: String 15 | ) 16 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/distribution/model/ArtistData.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.distribution.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class ArtistData( 8 | @SerialName("artist_name") 9 | val artistName: String, 10 | @SerialName("artist_id") 11 | val artistId: Long 12 | ) 13 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/distribution/model/Availability.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.distribution.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class Availability( 8 | @SerialName("availability_id") 9 | val availabilityId: Long, 10 | @SerialName("name") 11 | val name: String 12 | ) 13 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/distribution/model/Country.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.distribution.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class Country( 8 | @SerialName("country_code") 9 | val countryCode: String, 10 | @SerialName("country_name") 11 | val countryName: String, 12 | @SerialName("state") 13 | val states: List, 14 | ) 15 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/distribution/model/CoverImage.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.distribution.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class CoverImage( 8 | @SerialName("url") 9 | val url: String, 10 | @SerialName("extension") 11 | val extension: String 12 | ) 13 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/distribution/model/DeleteUserLabelResponse.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.distribution.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class DeleteUserLabelResponse( 8 | @SerialName("message") 9 | val message: String, 10 | @SerialName("success") 11 | val success: Boolean 12 | ) 13 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/distribution/model/DistributeFutureReleaseRequest.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.distribution.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class DistributeFutureReleaseRequest( 8 | @SerialName("uuid") 9 | val uuid: String, 10 | @SerialName("enable_distribute_to_future_outlets") 11 | val enableDistributeToFutureOutlets: Boolean 12 | ) 13 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/distribution/model/DistributeReleaseRequest.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.distribution.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class DistributeReleaseRequest( 8 | @SerialName("uuid") 9 | val uuid: String, 10 | @SerialName("release_id") 11 | val releaseId: Long? = null, 12 | @SerialName("outlets_details") 13 | val outletsDetails: List? = null 14 | ) 15 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/distribution/model/DistributeReleaseResponse.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.distribution.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class DistributeReleaseResponse( 8 | @SerialName("message") 9 | val message: String, 10 | @SerialName("success") 11 | val success: Boolean, 12 | @SerialName("data") 13 | val releaseData: ReleaseData? = null, 14 | ) 15 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/distribution/model/DistributionOutletReleaseStatusResponse.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.distribution.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class DistributionOutletReleaseStatusResponse( 8 | @SerialName("success") 9 | val success: Boolean, 10 | @SerialName("message") 11 | val message: String, 12 | @SerialName("data") 13 | val outletReleaseStatuses: List? = null, 14 | ) 15 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/distribution/model/Error.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.distribution.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class Error( 8 | @SerialName("message") 9 | val message: String, 10 | @SerialName("code") 11 | val code: Int 12 | ) 13 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/distribution/model/ErrorField.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.distribution.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class ErrorField( 8 | @SerialName("fields") 9 | val fields: String? = null, 10 | @SerialName("message") 11 | val message: String? = null, 12 | ) 13 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/distribution/model/EvearaErrorResponse.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.distribution.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class EvearaErrorResponse( 8 | @SerialName("message") 9 | val message: String, 10 | @SerialName("success") 11 | val success: Boolean, 12 | @SerialName("errors") 13 | val errors: List? = null, 14 | @SerialName("status_code") 15 | val statusCode: Int? = null 16 | ) 17 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/distribution/model/EvearaSimpleResponse.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.distribution.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class EvearaSimpleResponse( 8 | @SerialName("message") 9 | val message: String, 10 | @SerialName("success") 11 | val success: Boolean 12 | ) 13 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/distribution/model/FeaturedArtist.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.distribution.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class FeaturedArtist( 8 | @SerialName("artist_id") 9 | val artistId: Long, 10 | @SerialName("name") 11 | val name: String 12 | ) 13 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/distribution/model/Genre.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.distribution.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class Genre( 8 | @SerialName("genre_id") 9 | val genreId: Long, 10 | @SerialName("name") 11 | val name: String 12 | ) 13 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/distribution/model/GetAlbumResponse.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.distribution.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class GetAlbumResponse( 8 | @SerialName("message") 9 | val message: String, 10 | @SerialName("success") 11 | val success: Boolean, 12 | @SerialName("total_records") 13 | val totalRecords: Long, 14 | @SerialName("data") 15 | val albumData: List 16 | ) 17 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/distribution/model/GetArtistResponse.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.distribution.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class GetArtistResponse( 8 | @SerialName("message") 9 | val message: String, 10 | @SerialName("success") 11 | val success: Boolean, 12 | @SerialName("total_records") 13 | val totalRecords: Long, 14 | @SerialName("data") 15 | val artists: List, 16 | ) 17 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/distribution/model/GetCountriesResponse.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.distribution.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class GetCountriesResponse( 8 | @SerialName("message") 9 | val message: String, 10 | @SerialName("success") 11 | val success: Boolean, 12 | @SerialName("data") 13 | val countries: List 14 | ) 15 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/distribution/model/GetDateResponse.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.distribution.model 2 | 3 | import kotlinx.serialization.Contextual 4 | import kotlinx.serialization.Serializable 5 | import java.time.LocalDate 6 | 7 | @Serializable 8 | data class GetDateResponse( 9 | @Contextual 10 | val date: LocalDate 11 | ) 12 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/distribution/model/GetGenresResponse.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.distribution.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class GetGenresResponse( 8 | @SerialName("message") 9 | val message: String, 10 | @SerialName("success") 11 | val success: Boolean, 12 | @SerialName("data") 13 | val genres: List 14 | ) 15 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/distribution/model/GetLanguagesResponse.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.distribution.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class GetLanguagesResponse( 8 | @SerialName("success") 9 | val success: Boolean, 10 | @SerialName("data") 11 | val languages: List 12 | ) 13 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/distribution/model/GetOutletProfileNamesResponse.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.distribution.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class GetOutletProfileNamesResponse( 8 | @SerialName("success") 9 | val success: Boolean, 10 | @SerialName("message") 11 | val message: String, 12 | @SerialName("data") 13 | val outletProfileNames: List 14 | ) 15 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/distribution/model/GetOutletsResponse.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.distribution.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class GetOutletsResponse( 8 | @SerialName("success") 9 | val success: Boolean, 10 | @SerialName("message") 11 | val message: String, 12 | @SerialName("data") 13 | val outlets: List 14 | ) 15 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/distribution/model/GetParticipantsResponse.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.distribution.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class GetParticipantsResponse( 8 | @SerialName("message") 9 | val message: String, 10 | @SerialName("success") 11 | val success: Boolean, 12 | @SerialName("total_records") 13 | val totalRecords: Long, 14 | @SerialName("data") 15 | val participantData: List 16 | ) 17 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/distribution/model/GetPayoutBalanceResponse.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.distribution.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class GetPayoutBalanceResponse( 8 | @SerialName("success") 9 | val success: Boolean, 10 | @SerialName("message") 11 | val message: String, 12 | @SerialName("data") 13 | val balances: List 14 | ) 15 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/distribution/model/GetPayoutHistoryResponse.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.distribution.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class GetPayoutHistoryResponse( 8 | @SerialName("success") 9 | val success: Boolean, 10 | @SerialName("message") 11 | val message: String, 12 | @SerialName("data") 13 | val payoutHistories: List 14 | ) 15 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/distribution/model/GetRolesResponse.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.distribution.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class GetRolesResponse( 8 | @SerialName("message") 9 | val message: String, 10 | @SerialName("success") 11 | val success: Boolean, 12 | @SerialName("data") 13 | val roles: List 14 | ) 15 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/distribution/model/GetSmartLinksResponse.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.distribution.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class GetSmartLinksResponse( 8 | @SerialName("success") 9 | val success: Boolean, 10 | @SerialName("message") 11 | val message: String? = null, 12 | @SerialName("data") 13 | val data: List? = null, 14 | ) 15 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/distribution/model/GetTrackStatusResponse.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.distribution.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class GetTrackStatusResponse( 8 | @SerialName("success") 9 | val success: Boolean, 10 | @SerialName("message") 11 | val message: String, 12 | @SerialName("track_status") 13 | val trackStatus: TrackStatus 14 | ) 15 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/distribution/model/GetTracksResponse.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.distribution.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class GetTracksResponse( 8 | @SerialName("message") 9 | val message: String, 10 | @SerialName("success") 11 | val success: Boolean, 12 | @SerialName("total_records") 13 | val totalRecords: Long, 14 | @SerialName("data") 15 | val trackData: List? = null 16 | ) 17 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/distribution/model/GetUserLabelResponse.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.distribution.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class GetUserLabelResponse( 8 | @SerialName("message") 9 | val message: String, 10 | @SerialName("success") 11 | val success: Boolean, 12 | @SerialName("total_records") 13 | val totalRecords: Long, 14 | @SerialName("data") 15 | val userLabelData: List 16 | ) 17 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/distribution/model/GetUserResponse.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.distribution.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class GetUserResponse( 8 | @SerialName("message") 9 | val message: String, 10 | @SerialName("success") 11 | val success: Boolean, 12 | @SerialName("total_records") 13 | val totalRecords: Long, 14 | @SerialName("data") 15 | val users: List, 16 | ) 17 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/distribution/model/GetUserSubscriptionResponse.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.distribution.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class GetUserSubscriptionResponse( 8 | @SerialName("message") 9 | val message: String, 10 | @SerialName("total_records") 11 | val totalRecords: Long, 12 | @SerialName("success") 13 | val success: Boolean, 14 | @SerialName("data") 15 | val subscriptions: List 16 | ) 17 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/distribution/model/InitiatePayoutResponse.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.distribution.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class InitiatePayoutResponse( 8 | @SerialName("success") 9 | val success: Boolean, 10 | @SerialName("message") 11 | val message: String, 12 | @SerialName("participants_ids") 13 | val participantIds: List 14 | ) 15 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/distribution/model/LabelData.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.distribution.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class LabelData( 8 | @SerialName("label_name") 9 | val labelName: String, 10 | @SerialName("label_id") 11 | val labelId: Long 12 | ) 13 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/distribution/model/Language.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.distribution.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class Language( 8 | @SerialName("language_code") 9 | val code: String, 10 | @SerialName("language_name") 11 | val name: String 12 | ) 13 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/distribution/model/Outlet.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.distribution.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class Outlet( 8 | @SerialName("outlet_name") 9 | val outletName: String? = null, 10 | @SerialName("outlet_id") 11 | val outletId: String? = null, 12 | ) 13 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/distribution/model/OutletProfile.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.distribution.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class OutletProfile( 8 | @SerialName("id") 9 | val id: Long, 10 | @SerialName("name") 11 | val name: String? = null, 12 | @SerialName("profile_url") 13 | val profileUrl: String, 14 | /** 15 | * Only used for AudioMack 16 | */ 17 | @SerialName("profile_id") 18 | val profileId: String? = null, 19 | ) 20 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/distribution/model/OutletProfileName.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.distribution.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class OutletProfileName( 8 | @SerialName("id") 9 | val id: Long, 10 | @SerialName("name") 11 | val name: String, 12 | ) 13 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/distribution/model/OutletStatus.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.distribution.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class OutletStatus( 8 | @SerialName("status_code") 9 | val statusCode: OutletStatusCode, 10 | @SerialName("status_name") 11 | val statusName: String 12 | ) 13 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/distribution/model/Participant.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.distribution.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class Participant( 8 | @SerialName("id") 9 | val id: Long, 10 | @SerialName("role_id") 11 | val roleId: List, 12 | // should always be 100 for the NEWM Participant 13 | @SerialName("payout_share_percentage") 14 | val payoutSharePercentage: Int 15 | ) 16 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/distribution/model/ParticipantData.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.distribution.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class ParticipantData( 8 | @SerialName("participant_id") 9 | val participantId: Long, 10 | @SerialName("ipn") 11 | val ipn: String, 12 | @SerialName("isni") 13 | val isni: String, 14 | @SerialName("is_active") 15 | val isActive: Int, 16 | @SerialName("removable") 17 | val removable: Boolean, 18 | @SerialName("name") 19 | val name: String 20 | ) 21 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/distribution/model/ParticipantX.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.distribution.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class ParticipantX( 8 | @SerialName("participant_id") 9 | val participantId: Long, 10 | @SerialName("participant_name") 11 | val participantName: String, 12 | @SerialName("roles") 13 | val roles: List, 14 | @SerialName("payout_share_percentage") 15 | val payoutSharePercentage: Int 16 | ) 17 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/distribution/model/PayoutBalance.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.distribution.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class PayoutBalance( 8 | @SerialName("currency") 9 | val currency: String, 10 | @SerialName("participant_id") 11 | val participantId: String, 12 | @SerialName("amount_to_pay") 13 | val amountToPay: String, 14 | @SerialName("name") 15 | val name: String 16 | ) 17 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/distribution/model/PayoutHistory.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.distribution.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class PayoutHistory( 8 | @SerialName("payout_amount") 9 | val payoutAmount: String, 10 | @SerialName("currency") 11 | val currency: String, 12 | @SerialName("participant_id") 13 | val participantId: String, 14 | @SerialName("paid_date") 15 | val paidDate: String, 16 | @SerialName("payout_status") 17 | val payoutStatus: PayoutStatus, 18 | @SerialName("name") 19 | val name: String 20 | ) 21 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/distribution/model/PayoutStatus.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.distribution.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class PayoutStatus( 8 | @SerialName("status_code") 9 | val statusCode: PayoutStatusCode, 10 | @SerialName("status_name") 11 | val statusName: String 12 | ) 13 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/distribution/model/Preview.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.distribution.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class Preview( 8 | @SerialName("start_at") 9 | val startAt: Long, 10 | @SerialName("duration") 11 | val duration: Long 12 | ) 13 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/distribution/model/PriceCode.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.distribution.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class PriceCode( 8 | @SerialName("album_price_id") 9 | val albumPriceId: Long, 10 | @SerialName("track_price_id") 11 | val trackPriceId: Long, 12 | ) 13 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/distribution/model/PriceCodeList.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.distribution.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class PriceCodeList( 8 | @SerialName("album") 9 | val albumPrices: List, 10 | @SerialName("track") 11 | val trackPrices: List 12 | ) 13 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/distribution/model/ReleaseData.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.distribution.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class ReleaseData( 8 | @SerialName("albumStatus") 9 | val albumStatus: String, 10 | @SerialName("errorFields") 11 | val errorFields: List? = null, 12 | ) 13 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/distribution/model/Role.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.distribution.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class Role( 8 | @SerialName("role_id") 9 | val roleId: Long, 10 | @SerialName("name") 11 | val name: String 12 | ) 13 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/distribution/model/RoleX.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.distribution.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class RoleX( 8 | @SerialName("role_id") 9 | val roleId: String, 10 | @SerialName("role_name") 11 | val roleName: String 12 | ) 13 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/distribution/model/SmartLink.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.distribution.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class SmartLink( 8 | @SerialName("store_name") 9 | val storeName: String, 10 | @SerialName("smart_link_url") 11 | val url: String 12 | ) 13 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/distribution/model/Sony360.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.distribution.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class Sony360( 8 | @SerialName("L0") 9 | val l0: String? = null, 10 | @SerialName("L1") 11 | val l1: String? = null, 12 | @SerialName("L2") 13 | val l2: String? = null, 14 | @SerialName("L3") 15 | val l3: String? = null, 16 | ) 17 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/distribution/model/State.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.distribution.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class State( 8 | @SerialName("state_code") 9 | val stateCode: String, 10 | @SerialName("state_name") 11 | val stateName: String, 12 | ) 13 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/distribution/model/Subscription.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.distribution.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class Subscription( 8 | @SerialName("subscription_id") 9 | val subscriptionId: Long, 10 | @SerialName("partner_reference_id") 11 | val partnerReferenceId: String 12 | ) 13 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/distribution/model/SubscriptionX.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.distribution.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class SubscriptionX( 8 | @SerialName("expiration_date") 9 | val expirationDate: String, 10 | @SerialName("subscription_id") 11 | val subscriptionId: Long, 12 | @SerialName("subscription_name") 13 | val subscriptionName: String 14 | ) 15 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/distribution/model/Track.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.distribution.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class Track( 8 | @SerialName("track_id") 9 | val trackId: Long, 10 | @SerialName("artists") 11 | val artistIds: List, 12 | @SerialName("featured_artists") 13 | val featuredArtists: List?, 14 | @SerialName("preview") 15 | val preview: Preview?, 16 | @SerialName("participant") 17 | val participants: List, 18 | @SerialName("instrumental") 19 | val instrumental: Boolean, 20 | ) 21 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/distribution/model/TrackPrice.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.distribution.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class TrackPrice( 8 | @SerialName("price") 9 | val price: Double, 10 | @SerialName("price_id") 11 | val priceId: Long, 12 | ) 13 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/distribution/model/TrackStatus.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.distribution.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class TrackStatus( 8 | @SerialName("stereo") 9 | val stereo: String? = null, 10 | @SerialName("dolby") 11 | val dolby: String? = null, 12 | @SerialName("sony360") 13 | val sony360: Sony360? = null, 14 | ) 15 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/distribution/model/UpdateArtistRequest.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.distribution.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class UpdateArtistRequest( 8 | @SerialName("uuid") 9 | val uuid: String, 10 | @SerialName("name") 11 | val name: String, 12 | @SerialName("country") 13 | val country: String? = null, 14 | @SerialName("outlets_profile") 15 | val outletProfiles: List? = null 16 | ) 17 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/distribution/model/UpdateArtistResponse.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.distribution.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class UpdateArtistResponse( 8 | @SerialName("message") 9 | val message: String, 10 | @SerialName("success") 11 | val success: Boolean, 12 | @SerialName("data") 13 | val artistData: ArtistData? = null, 14 | ) 15 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/distribution/model/UpdateUserLabelRequest.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.distribution.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class UpdateUserLabelRequest( 8 | @SerialName("uuid") 9 | val uuid: String, 10 | @SerialName("name") 11 | val name: String 12 | ) 13 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/distribution/model/UpdateUserLabelResponse.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.distribution.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class UpdateUserLabelResponse( 8 | @SerialName("message") 9 | val message: String, 10 | @SerialName("success") 11 | val success: Boolean, 12 | @SerialName("data") 13 | val labelData: LabelData? = null, 14 | ) 15 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/distribution/model/UpdateUserRequest.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.distribution.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class UpdateUserRequest( 8 | @SerialName("uuid") 9 | val uuid: String, 10 | @SerialName("first_name") 11 | val firstName: String, 12 | @SerialName("sur_name") 13 | val lastName: String, 14 | @SerialName("email") 15 | val email: String, 16 | ) 17 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/distribution/model/UserLabelData.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.distribution.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class UserLabelData( 8 | @SerialName("releases") 9 | val releases: Int? = null, 10 | @SerialName("label_id") 11 | val labelId: Long? = null, 12 | @SerialName("is_active") 13 | val isActive: Int? = null, 14 | @SerialName("name") 15 | val name: String? = null, 16 | @SerialName("removable") 17 | val removable: Boolean? = null 18 | ) 19 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/distribution/model/UserResponse.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.distribution.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class UserResponse( 8 | @SerialName("uuid") 9 | val uuid: String, 10 | @SerialName("first_name") 11 | val firstName: String, 12 | @SerialName("sur_name") 13 | val lastName: String, 14 | @SerialName("email") 15 | val email: String, 16 | ) 17 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/distribution/model/UserSubscription.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.distribution.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class UserSubscription( 8 | @SerialName("subscription_id") 9 | val subscriptionId: Long, 10 | @SerialName("my_subscription_id") 11 | val userSubscriptionId: Long 12 | ) 13 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/distribution/model/ValidateAlbumResponse.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.distribution.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class ValidateAlbumResponse( 8 | @SerialName("message") 9 | val message: String, 10 | @SerialName("success") 11 | val success: Boolean, 12 | @SerialName("data") 13 | val validateData: ValidateData 14 | ) 15 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/distribution/model/ValidateData.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.distribution.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class ValidateData( 8 | @SerialName("album_status") 9 | val albumStatus: AlbumStatus, 10 | @SerialName("error_fields") 11 | val errorFields: List? = null, 12 | ) 13 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/doc/DocumentationRoutes.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.doc 2 | 3 | import io.github.oshai.kotlinlogging.KotlinLogging 4 | import io.ktor.server.plugins.swagger.swaggerUI 5 | import io.ktor.server.routing.Routing 6 | 7 | private val log = KotlinLogging.logger {} 8 | 9 | /** 10 | * Routes that are not protected by authentication for serving the open api documentation. 11 | */ 12 | fun Routing.createOpenApiDocumentationRoutes() { 13 | try { 14 | swaggerUI(path = "openapi", swaggerFile = "openapi/documentation.yaml") 15 | } catch (e: Throwable) { 16 | log.error(e) { "Failed to create open api documentation routes" } 17 | throw e 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/dripdropz/DripDropzModule.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.dripdropz 2 | 3 | import io.newm.server.features.dripdropz.repo.DripDropzRepository 4 | import io.newm.server.features.dripdropz.repo.DripDropzRepositoryImpl 5 | import org.koin.dsl.module 6 | 7 | val dripDropzKoinModule = 8 | module { 9 | single { DripDropzRepositoryImpl(get(), get()) } 10 | } 11 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/dripdropz/model/AvailableToken.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.dripdropz.model 2 | 3 | import kotlinx.serialization.Contextual 4 | import kotlinx.serialization.SerialName 5 | import kotlinx.serialization.Serializable 6 | import java.math.BigDecimal 7 | 8 | @Serializable 9 | data class AvailableToken( 10 | @SerialName("token_policy") 11 | val tokenPolicy: String, 12 | @SerialName("token_asset_id") 13 | val tokenAssetId: String, 14 | @Contextual 15 | @SerialName("available_quantity") 16 | val availableQuantity: BigDecimal, 17 | ) 18 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/dripdropz/model/CheckRequest.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.dripdropz.model 2 | 3 | import kotlinx.serialization.Serializable 4 | 5 | @Serializable 6 | data class CheckRequest( 7 | val address: String 8 | ) 9 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/dripdropz/model/CheckResponse.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.dripdropz.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class CheckResponse( 8 | @SerialName("data") 9 | val data: Data 10 | ) { 11 | @Serializable 12 | data class Data( 13 | @SerialName("available_tokens") 14 | val availableTokens: List 15 | ) 16 | } 17 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/dripdropz/repo/DripDropzRepository.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.dripdropz.repo 2 | 3 | import io.newm.server.features.dripdropz.model.AvailableToken 4 | 5 | interface DripDropzRepository { 6 | suspend fun checkAvailableTokens(address: String): List 7 | } 8 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/earnings/EarningsKoinModule.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.earnings 2 | 3 | import io.newm.server.features.earnings.repo.EarningsRepository 4 | import io.newm.server.features.earnings.repo.EarningsRepositoryImpl 5 | import org.koin.dsl.module 6 | 7 | val earningsKoinModule = 8 | module { 9 | single { EarningsRepositoryImpl(get(), get(), get(), get(), get()) } 10 | } 11 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/earnings/model/ClaimOrderRequest.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.earnings.model 2 | 3 | import io.newm.chain.grpc.Utxo 4 | import io.newm.server.ktx.cborHexToUtxos 5 | import kotlinx.serialization.Serializable 6 | 7 | @Serializable 8 | data class ClaimOrderRequest( 9 | val walletAddress: String, 10 | val changeAddress: String, 11 | val utxoCborHexList: List, 12 | ) { 13 | val utxos: List by lazy { utxoCborHexList.cborHexToUtxos() } 14 | } 15 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/earnings/model/ClaimOrderStatus.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.earnings.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | enum class ClaimOrderStatus { 8 | @SerialName("Pending") 9 | Pending, 10 | 11 | @SerialName("Processing") 12 | Processing, 13 | 14 | @SerialName("Completed") 15 | Completed, 16 | 17 | @SerialName("Timeout") 18 | Timeout, 19 | 20 | @SerialName("Blocked") 21 | Blocked, 22 | 23 | @SerialName("Failed") 24 | Failed, 25 | } 26 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/earnings/model/GetEarningsBySongIdResponse.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.earnings.model 2 | 3 | import kotlinx.serialization.Serializable 4 | 5 | @Serializable 6 | data class GetEarningsBySongIdResponse( 7 | val earnings: List, 8 | val totalAmount: Long, 9 | ) 10 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/earnings/model/GetEarningsResponse.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.earnings.model 2 | 3 | import kotlinx.serialization.Serializable 4 | 5 | @Serializable 6 | data class GetEarningsResponse( 7 | val earnings: List, 8 | val totalClaimed: Long, 9 | val amountCborHex: String, 10 | ) 11 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/email/EmailKoinModule.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.email 2 | 3 | import io.newm.server.features.email.repo.EmailRepository 4 | import io.newm.server.features.email.repo.EmailRepositoryImpl 5 | import org.koin.dsl.module 6 | 7 | val emailKoinModule = 8 | module { 9 | single { EmailRepositoryImpl(get()) } 10 | } 11 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/email/repo/EmailRepository.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.email.repo 2 | 3 | interface EmailRepository { 4 | suspend fun send( 5 | to: String, 6 | subject: String, 7 | messageUrl: String, 8 | messageArgs: Map = emptyMap() 9 | ) 10 | 11 | suspend fun send( 12 | to: List, 13 | bcc: List, 14 | subject: String, 15 | messageUrl: String, 16 | messageArgs: Map = emptyMap() 17 | ) 18 | } 19 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/idenfy/model/IdenfyCreateSessionRequest.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.idenfy.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class IdenfyCreateSessionRequest( 8 | @SerialName("clientId") 9 | val clientId: String, 10 | @SerialName("successUrl") 11 | val successUrl: String, 12 | @SerialName("errorUrl") 13 | val errorUrl: String, 14 | ) 15 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/idenfy/model/IdenfyCreateSessionResponse.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.idenfy.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class IdenfyCreateSessionResponse( 8 | @SerialName("authToken") 9 | val authToken: String, 10 | @SerialName("expiryTime") 11 | val expiryTime: Int 12 | ) 13 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/idenfy/repo/IdenfyRepository.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.idenfy.repo 2 | 3 | import io.newm.server.features.idenfy.model.IdenfyCreateSessionResponse 4 | import io.newm.server.features.idenfy.model.IdenfySessionResult 5 | import io.newm.server.typealiases.UserId 6 | 7 | interface IdenfyRepository { 8 | suspend fun createSession(userId: UserId): IdenfyCreateSessionResponse 9 | 10 | suspend fun processSessionResult(result: IdenfySessionResult) 11 | } 12 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/marketplace/MarketplaceKoinModule.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.marketplace 2 | 3 | import io.newm.server.features.marketplace.daemon.MarketplaceMonitorDaemon 4 | import io.newm.server.features.marketplace.repo.MarketplaceRepository 5 | import io.newm.server.features.marketplace.repo.MarketplaceRepositoryImpl 6 | import io.newm.shared.daemon.Daemon 7 | import org.koin.dsl.module 8 | 9 | val marketplaceKoinModule = 10 | module { 11 | single { MarketplaceMonitorDaemon(get(), get(), get()) } 12 | single { MarketplaceRepositoryImpl(get(), get(), get(), get(), get()) } 13 | } 14 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/marketplace/database/MarketplaceBookmarkTable.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.marketplace.database 2 | 3 | import io.newm.server.typealiases.BookmarkId 4 | import org.jetbrains.exposed.dao.id.EntityID 5 | import org.jetbrains.exposed.dao.id.IdTable 6 | import org.jetbrains.exposed.sql.Column 7 | 8 | object MarketplaceBookmarkTable : IdTable(name = "marketplace_bookmarks") { 9 | override val id: Column> = text("id").entityId() 10 | val txId: Column = text("txid") 11 | val block: Column = long("block") 12 | val slot: Column = long("slot") 13 | } 14 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/marketplace/database/MarketplaceSaleOwnerTable.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.marketplace.database 2 | 3 | import org.jetbrains.exposed.dao.id.UUIDTable 4 | import org.jetbrains.exposed.sql.Column 5 | import org.jetbrains.exposed.sql.javatime.CurrentDateTime 6 | import org.jetbrains.exposed.sql.javatime.datetime 7 | import java.time.LocalDateTime 8 | 9 | object MarketplaceSaleOwnerTable : UUIDTable(name = "marketplace_sale_owners") { 10 | val createdAt: Column = datetime("created_at").defaultExpression(CurrentDateTime) 11 | val pointerPolicyId: Column = text("pointer_policy_id") 12 | val pointerAssetName: Column = text("pointer_asset_name") 13 | val email: Column = text("email") 14 | } 15 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/marketplace/model/CostAmountConversions.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.marketplace.model 2 | 3 | data class CostAmountConversions( 4 | val usd: String, 5 | val newm: String 6 | ) 7 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/marketplace/model/OrderAmountRequest.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.marketplace.model 2 | 3 | import io.newm.server.typealiases.SaleId 4 | import kotlinx.serialization.Contextual 5 | import kotlinx.serialization.Serializable 6 | 7 | @Serializable 8 | data class OrderAmountRequest( 9 | @Contextual 10 | val saleId: SaleId, 11 | val bundleQuantity: Long, 12 | val incentiveAmount: Long? 13 | ) 14 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/marketplace/model/OrderAmountResponse.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.marketplace.model 2 | 3 | import io.newm.server.typealiases.PendingOrderId 4 | import kotlinx.serialization.Contextual 5 | import kotlinx.serialization.Serializable 6 | 7 | @Serializable 8 | data class OrderAmountResponse( 9 | @Contextual 10 | val orderId: PendingOrderId, 11 | val amountCborHex: String 12 | ) 13 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/marketplace/model/OrderFees.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.marketplace.model 2 | 3 | import kotlinx.serialization.Serializable 4 | 5 | @Serializable 6 | data class OrderFees( 7 | val serviceFeePercentage: Double, 8 | val profitAmountUsd: Double 9 | ) 10 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/marketplace/model/OrderTransactionRequest.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.marketplace.model 2 | 3 | import io.newm.chain.grpc.Utxo 4 | import io.newm.server.ktx.cborHexToUtxos 5 | import io.newm.server.typealiases.PendingOrderId 6 | import kotlinx.serialization.Contextual 7 | import kotlinx.serialization.Serializable 8 | 9 | @Serializable 10 | data class OrderTransactionRequest( 11 | @Contextual 12 | val orderId: PendingOrderId, 13 | val changeAddress: String, 14 | val utxoCborHexList: List, 15 | ) { 16 | val utxos: List by lazy { utxoCborHexList.cborHexToUtxos() } 17 | } 18 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/marketplace/model/OrderTransactionResponse.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.marketplace.model 2 | 3 | import kotlinx.serialization.Serializable 4 | 5 | @Serializable 6 | data class OrderTransactionResponse( 7 | val txCborHex: String 8 | ) 9 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/marketplace/model/QueueTransaction.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.marketplace.model 2 | 3 | data class QueueTransaction( 4 | override val tokens: List, 5 | override val ownerAddress: String, 6 | val numberOfBundles: Long, 7 | val incentive: Token, 8 | val pointerAssetName: String 9 | ) : Transaction 10 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/marketplace/model/SaleEndAmountRequest.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.marketplace.model 2 | 3 | import io.newm.server.typealiases.SaleId 4 | import kotlinx.serialization.Contextual 5 | import kotlinx.serialization.Serializable 6 | 7 | @Serializable 8 | data class SaleEndAmountRequest( 9 | @Contextual 10 | val saleId: SaleId 11 | ) 12 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/marketplace/model/SaleEndAmountResponse.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.marketplace.model 2 | 3 | import kotlinx.serialization.Serializable 4 | 5 | @Serializable 6 | data class SaleEndAmountResponse( 7 | val amountCborHex: String 8 | ) 9 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/marketplace/model/SaleEndTransactionRequest.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.marketplace.model 2 | 3 | import io.newm.chain.grpc.Utxo 4 | import io.newm.server.ktx.cborHexToUtxos 5 | import io.newm.server.typealiases.SaleId 6 | import kotlinx.serialization.Contextual 7 | import kotlinx.serialization.Serializable 8 | 9 | @Serializable 10 | data class SaleEndTransactionRequest( 11 | @Contextual 12 | val saleId: SaleId, 13 | val changeAddress: String, 14 | val utxoCborHexList: List, 15 | ) { 16 | val utxos: List by lazy { utxoCborHexList.cborHexToUtxos() } 17 | } 18 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/marketplace/model/SaleEndTransactionResponse.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.marketplace.model 2 | 3 | import kotlinx.serialization.Serializable 4 | 5 | @Serializable 6 | data class SaleEndTransactionResponse( 7 | val txCborHex: String 8 | ) 9 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/marketplace/model/SaleStartAmountRequest.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.marketplace.model 2 | 3 | import kotlinx.serialization.Serializable 4 | 5 | @Serializable 6 | data class SaleStartAmountRequest( 7 | val ownerAddress: String, 8 | val bundlePolicyId: String, 9 | val bundleAssetName: String, 10 | val bundleAmount: Long, 11 | val costPolicyId: String?, // Optional: if missing defaults to NEWM token 12 | val costAssetName: String?, // Optional: if missing defaults to NEWM token 13 | val costAmount: Long, 14 | val totalBundleQuantity: Long 15 | ) 16 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/marketplace/model/SaleStartAmountResponse.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.marketplace.model 2 | 3 | import io.newm.server.typealiases.PendingSaleId 4 | import kotlinx.serialization.Contextual 5 | import kotlinx.serialization.Serializable 6 | 7 | @Serializable 8 | data class SaleStartAmountResponse( 9 | @Contextual 10 | val saleId: PendingSaleId, 11 | val amountCborHex: String 12 | ) 13 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/marketplace/model/SaleStartTransactionRequest.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.marketplace.model 2 | 3 | import io.newm.chain.grpc.Utxo 4 | import io.newm.server.ktx.cborHexToUtxos 5 | import io.newm.server.typealiases.PendingSaleId 6 | import kotlinx.serialization.Contextual 7 | import kotlinx.serialization.Serializable 8 | 9 | @Serializable 10 | data class SaleStartTransactionRequest( 11 | @Contextual 12 | val saleId: PendingSaleId, 13 | val changeAddress: String, 14 | val email: String?, // Optional, to get notifications 15 | val utxoCborHexList: List, 16 | ) { 17 | val utxos: List by lazy { utxoCborHexList.cborHexToUtxos() } 18 | } 19 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/marketplace/model/SaleStartTransactionResponse.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.marketplace.model 2 | 3 | import kotlinx.serialization.Serializable 4 | 5 | @Serializable 6 | data class SaleStartTransactionResponse( 7 | val txCborHex: String 8 | ) 9 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/marketplace/model/SaleStatus.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.marketplace.model 2 | 3 | enum class SaleStatus { 4 | Started, 5 | SoldOut, 6 | Ended 7 | } 8 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/marketplace/model/SaleTransaction.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.marketplace.model 2 | 3 | import io.newm.shared.ktx.orZero 4 | 5 | data class SaleTransaction( 6 | override val tokens: List, 7 | override val ownerAddress: String, 8 | val bundle: Token, 9 | val cost: Token, 10 | val maxBundleSize: Long 11 | ) : Transaction { 12 | val bundleQuantity: Long by lazy { getToken(bundle.policyId, bundle.assetName)?.amount.orZero() / bundle.amount } 13 | } 14 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/marketplace/model/Token.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.marketplace.model 2 | 3 | import io.newm.chain.util.hexStringToAssetName 4 | 5 | data class Token( 6 | val policyId: String, 7 | val assetName: String, 8 | val amount: Long 9 | ) { 10 | override fun toString(): String = "Token(policyId=$policyId,assetName=$assetName (${assetName.hexStringToAssetName()}),amount=$amount)" 11 | } 12 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/marketplace/model/Transaction.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.marketplace.model 2 | 3 | interface Transaction { 4 | val tokens: List 5 | val ownerAddress: String 6 | 7 | fun getToken(policyId: String): Token? = tokens.firstOrNull { it.policyId == policyId } 8 | 9 | fun getToken( 10 | policyId: String, 11 | assetName: String 12 | ): Token? = tokens.firstOrNull { it.policyId == policyId && it.assetName == assetName } 13 | } 14 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/minting/DistributeAndMintException.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.minting 2 | 3 | class DistributeAndMintException( 4 | message: String, 5 | cause: Throwable 6 | ) : RuntimeException(message, cause) 7 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/minting/ForceTrackToFailException.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.minting 2 | 3 | class ForceTrackToFailException( 4 | message: String 5 | ) : RuntimeException(message) 6 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/minting/MintingKoinModule.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.minting 2 | 3 | import io.newm.server.features.minting.repo.MintingRepository 4 | import io.newm.server.features.minting.repo.MintingRepositoryImpl 5 | import org.koin.dsl.module 6 | 7 | val mintingKoinModule = 8 | module { 9 | single { MintingRepositoryImpl(get(), get(), get(), get()) } 10 | } 11 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/minting/MintingStatusSqsMessage.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.minting 2 | 3 | import io.newm.server.features.song.model.MintingStatus 4 | import io.newm.server.typealiases.SongId 5 | import kotlinx.serialization.Contextual 6 | import kotlinx.serialization.Serializable 7 | 8 | @Serializable 9 | data class MintingStatusSqsMessage( 10 | @Contextual 11 | val songId: SongId, 12 | val mintingStatus: MintingStatus, 13 | ) 14 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/minting/model/MintInfo.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.minting.model 2 | 3 | /** 4 | * The result of a minting operation 5 | */ 6 | data class MintInfo( 7 | val transactionId: String, 8 | val policyId: String, 9 | val assetName: String, 10 | ) 11 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/minting/model/MintingStatusTransactionModel.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.minting.model 2 | 3 | import io.newm.server.typealiases.SongId 4 | import kotlinx.serialization.Contextual 5 | import kotlinx.serialization.Serializable 6 | import java.time.LocalDateTime 7 | import java.util.* 8 | 9 | @Serializable 10 | data class MintingStatusTransactionModel( 11 | @Contextual 12 | val id: UUID? = null, 13 | @Contextual 14 | val createdAt: LocalDateTime, 15 | val mintingStatus: String, 16 | val logMessage: String? = null, 17 | @Contextual 18 | val songId: SongId, 19 | ) 20 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/model/CountResponse.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.model 2 | 3 | import kotlinx.serialization.Serializable 4 | 5 | @Serializable 6 | data class CountResponse( 7 | val count: Long 8 | ) 9 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/nftcdn/NftCdnKoinModule.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.nftcdn 2 | 3 | import io.newm.server.features.nftcdn.repo.NftCdnRepository 4 | import io.newm.server.features.nftcdn.repo.NftCdnRepositoryImpl 5 | import org.koin.dsl.module 6 | 7 | val nftCdnKoinModule = 8 | module { 9 | single { NftCdnRepositoryImpl(get()) } 10 | } 11 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/nftcdn/repo/NftCdnRepository.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.nftcdn.repo 2 | 3 | interface NftCdnRepository { 4 | fun generateImageUrl(fingerprint: String): String 5 | 6 | fun generateFileUrl( 7 | fingerprint: String, 8 | index: Int 9 | ): String 10 | 11 | fun generateUrl( 12 | fingerprint: String, 13 | path: String, 14 | ): String 15 | } 16 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/playlist/PlaylistKoinModule.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.playlist 2 | 3 | import io.newm.server.features.playlist.repo.PlaylistRepository 4 | import io.newm.server.features.playlist.repo.PlaylistRepositoryImpl 5 | import org.koin.dsl.module 6 | 7 | val playlistKoinModule = 8 | module { 9 | single { PlaylistRepositoryImpl() } 10 | } 11 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/playlist/model/Playlist.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.playlist.model 2 | 3 | import io.newm.server.typealiases.UserId 4 | import kotlinx.serialization.Contextual 5 | import kotlinx.serialization.Serializable 6 | import java.time.LocalDateTime 7 | import java.util.UUID 8 | 9 | @Serializable 10 | data class Playlist( 11 | @Contextual 12 | val id: UUID? = null, 13 | @Contextual 14 | val createdAt: LocalDateTime? = null, 15 | @Contextual 16 | val ownerId: UserId? = null, 17 | val name: String? = null 18 | ) 19 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/playlist/model/PlaylistIdBody.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.playlist.model 2 | 3 | import kotlinx.serialization.Contextual 4 | import kotlinx.serialization.Serializable 5 | import java.util.UUID 6 | 7 | @Serializable 8 | data class PlaylistIdBody( 9 | @Contextual 10 | val playlistId: UUID 11 | ) 12 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/referralhero/ReferralHeroKoinModule.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.referralhero 2 | 3 | import io.newm.server.features.referralhero.repo.ReferralHeroRepository 4 | import io.newm.server.features.referralhero.repo.ReferralHeroRepositoryImpl 5 | import org.koin.dsl.module 6 | 7 | val referralHeroKoinModule = 8 | module { 9 | single { ReferralHeroRepositoryImpl(get(), get()) } 10 | } 11 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/referralhero/model/CommonResponse.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.referralhero.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class CommonResponse( 8 | val status: String, 9 | val message: String?, 10 | val code: String?, 11 | val data: Data? 12 | ) { 13 | val isStatusOk: Boolean 14 | get() = status == "ok" 15 | 16 | @Serializable 17 | data class Data( 18 | val response: String, 19 | val code: String, 20 | @SerialName("referral_status") 21 | val referralStatus: String? 22 | ) 23 | } 24 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/referralhero/model/ReferralHeroSubscriber.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.referralhero.model 2 | 3 | data class ReferralHeroSubscriber( 4 | val referralCode: String, 5 | val referralStatus: ReferralStatus 6 | ) 7 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/referralhero/model/ReferralStatus.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.referralhero.model 2 | 3 | enum class ReferralStatus { 4 | NotReferred, 5 | Pending, 6 | Unconfirmed, 7 | Confirmed 8 | } 9 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/referralhero/repo/ReferralHeroRepository.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.referralhero.repo 2 | 3 | import io.newm.server.features.referralhero.model.ReferralHeroSubscriber 4 | 5 | interface ReferralHeroRepository { 6 | suspend fun getOrCreateSubscriber( 7 | email: String, 8 | referrer: String? = null, 9 | ): ReferralHeroSubscriber? 10 | 11 | suspend fun trackReferralConversion(email: String): Boolean 12 | 13 | suspend fun confirmReferral(email: String): Boolean 14 | } 15 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/release/ReleaseKoinModule.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.release 2 | 3 | import io.newm.server.client.QUALIFIER_SPOTIFY_HTTP_CLIENT 4 | import io.newm.server.features.release.repo.OutletReleaseRepository 5 | import io.newm.server.features.release.repo.OutletReleaseRepositoryImpl 6 | import org.koin.dsl.module 7 | 8 | val releaseKoinModule = 9 | module { 10 | single { OutletReleaseRepositoryImpl(get(QUALIFIER_SPOTIFY_HTTP_CLIENT), get()) } 11 | } 12 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/release/model/SpotifyPlaylistRequest.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.release.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class SpotifyPlaylistRequest( 8 | @SerialName("uris") 9 | val uris: List, 10 | @SerialName("position") 11 | val position: Int, 12 | ) 13 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/release/model/SpotifySearchResponse.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.release.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class SpotifySearchResponse( 8 | @SerialName("tracks") val tracks: Tracks 9 | ) 10 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/release/model/SpotifyTrackItem.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.release.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class SpotifyTrackItem( 8 | @SerialName("id") val id: String, 9 | @SerialName("track_number") val trackNumber: Int, 10 | @SerialName("uri") val uri: String, 11 | @SerialName("external_urls") val externalUrls: Map 12 | ) 13 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/release/model/Tracks.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.release.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class Tracks( 8 | @SerialName("total") val total: Int, 9 | @SerialName("items") val items: ArrayList = arrayListOf() 10 | ) 11 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/release/repo/OutletReleaseRepository.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.release.repo 2 | 3 | import io.ktor.client.statement.HttpResponse 4 | import io.newm.server.features.distribution.model.SmartLink 5 | import io.newm.server.typealiases.SongId 6 | 7 | interface OutletReleaseRepository { 8 | suspend fun isSongReleased(songId: SongId): Boolean 9 | 10 | suspend fun addSongToPlaylist(trackUri: String): HttpResponse 11 | 12 | suspend fun getSmartLinks(songId: SongId): List 13 | } 14 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/song/SongKoinModule.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.song 2 | 3 | import io.newm.server.features.song.repo.SongRepository 4 | import io.newm.server.features.song.repo.SongRepositoryImpl 5 | import org.koin.dsl.module 6 | 7 | val songKoinModule = 8 | module { 9 | single { SongRepositoryImpl(get(), get(), get(), get(), get(), get(), get(), get(), get()) } 10 | } 11 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/song/model/AudioEncodingStatus.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.song.model 2 | 3 | enum class AudioEncodingStatus { 4 | NotStarted, 5 | Started, 6 | Completed, 7 | Failed 8 | } 9 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/song/model/AudioStreamResponse.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.song.model 2 | 3 | import io.ktor.http.Cookie 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class AudioStreamResponse( 8 | val url: String 9 | ) { 10 | constructor(data: AudioStreamData) : this(data.url) 11 | } 12 | 13 | interface AudioStreamData { 14 | val url: String 15 | val cookies: List 16 | } 17 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/song/model/AudioUploadReport.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.song.model 2 | 3 | import kotlinx.serialization.Serializable 4 | 5 | @Serializable 6 | data class AudioUploadReport( 7 | val url: String, 8 | val mimeType: String, 9 | // in bytes 10 | val fileSize: Long, 11 | // in seconds 12 | val duration: Int, 13 | // in Hz 14 | val sampleRate: Int 15 | ) 16 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/song/model/MarketplaceStatus.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.song.model 2 | 3 | enum class MarketplaceStatus { 4 | NotSelling, 5 | Selling 6 | } 7 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/song/model/MintPaymentRequest.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.song.model 2 | 3 | import io.newm.chain.grpc.Utxo 4 | import io.newm.server.ktx.cborHexToUtxos 5 | import kotlinx.serialization.Serializable 6 | 7 | @Serializable 8 | data class MintPaymentRequest( 9 | val changeAddress: String, 10 | val utxoCborHexList: List? = null, 11 | ) { 12 | val utxos: List by lazy { utxoCborHexList.cborHexToUtxos() } 13 | } 14 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/song/model/RefundPaymentResponse.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.song.model 2 | 3 | import kotlinx.serialization.Serializable 4 | 5 | @Serializable 6 | data class RefundPaymentResponse( 7 | val transactionId: String, 8 | val message: String, 9 | ) 10 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/song/model/ReleaseBarcodeType.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.song.model 2 | 3 | enum class ReleaseBarcodeType { 4 | Upc, // Universal Product Codes (UPC) - 0 5 | Ean, // International Article Number (EAN) - 1 6 | Jan, // Japanese Article Number (JAN) - 2 7 | } 8 | 9 | fun String.toSongBarcodeType(): ReleaseBarcodeType = 10 | if (this.equals("upc", ignoreCase = true)) { 11 | ReleaseBarcodeType.Upc 12 | } else if (this.equals("ean", ignoreCase = true)) { 13 | ReleaseBarcodeType.Ean 14 | } else if (this.equals("jan", ignoreCase = true)) { 15 | ReleaseBarcodeType.Jan 16 | } else { 17 | throw IllegalArgumentException("Invalid barcode type: $this") 18 | } 19 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/song/model/ReleaseType.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.song.model 2 | 3 | enum class ReleaseType { 4 | /** 5 | * The default release type if it doesn't fall into any other category. 6 | */ 7 | ALBUM, 8 | 9 | /** 10 | * Only one track is allowed. 11 | */ 12 | SINGLE, 13 | 14 | /** 15 | * The release should have more than four main artists. 16 | */ 17 | COMPILATION_ALBUM, 18 | 19 | /** 20 | * Combined tracks duration cannot exceed 30 minutes. 21 | * Can add only up to six tracks. 22 | * If number of tracks are three or less, at least one track should be 10 minutes long. 23 | */ 24 | EP, 25 | } 26 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/song/model/SongIdBody.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.song.model 2 | 3 | import io.newm.server.typealiases.SongId 4 | import kotlinx.serialization.Contextual 5 | import kotlinx.serialization.Serializable 6 | 7 | @Serializable 8 | data class SongIdBody( 9 | @Contextual 10 | val songId: SongId 11 | ) 12 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/song/model/SongSmartLink.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.song.model 2 | 3 | import kotlinx.serialization.Contextual 4 | import kotlinx.serialization.Serializable 5 | import java.util.UUID 6 | 7 | @Serializable 8 | data class SongSmartLink( 9 | @Contextual 10 | val id: UUID, 11 | val storeName: String, 12 | val url: String 13 | ) 14 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/song/model/StreamTokenAgreementRequest.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.song.model 2 | 3 | import kotlinx.serialization.Serializable 4 | 5 | @Serializable 6 | data class StreamTokenAgreementRequest( 7 | val accepted: Boolean 8 | ) 9 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/user/model/UserIdBody.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.user.model 2 | 3 | import kotlinx.serialization.Contextual 4 | import kotlinx.serialization.Serializable 5 | import java.util.UUID 6 | 7 | @Serializable 8 | data class UserIdBody( 9 | @Contextual 10 | val userId: UUID 11 | ) 12 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/user/model/UserVerificationStatus.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.user.model 2 | 3 | enum class UserVerificationStatus { 4 | Unverified, 5 | Pending, 6 | Verified 7 | } 8 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/user/oauth/OAuthUser.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.user.oauth 2 | 3 | interface OAuthUser { 4 | val id: String 5 | val firstName: String? 6 | val lastName: String? 7 | val pictureUrl: String? 8 | val email: String? 9 | val isEmailVerified: Boolean? 10 | } 11 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/user/oauth/OAuthUserProvider.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.user.oauth 2 | 3 | import io.newm.server.auth.oauth.model.OAuthTokens 4 | 5 | interface OAuthUserProvider { 6 | suspend fun getUser(tokens: OAuthTokens): OAuthUser 7 | } 8 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/user/verify/OutletProfileUrlVerifier.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.user.verify 2 | 3 | /** 4 | * Verifies that the outlet profile URL is valid and that the NEWM stageOrFullName matches the outlet profile. 5 | */ 6 | interface OutletProfileUrlVerifier { 7 | @Throws(OutletProfileUrlVerificationException::class) 8 | suspend fun verify( 9 | outletProfileUrl: String, 10 | stageOrFullName: String 11 | ) 12 | } 13 | 14 | class OutletProfileUrlVerificationException( 15 | message: String 16 | ) : Exception(message) 17 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/walletconnection/WalletConnectionKoinModule.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.walletconnection 2 | 3 | import io.newm.server.features.walletconnection.repo.WalletConnectionRepository 4 | import io.newm.server.features.walletconnection.repo.WalletConnectionRepositoryImpl 5 | import org.koin.dsl.module 6 | 7 | val walletConnectionKoinModule = 8 | module { 9 | single { 10 | WalletConnectionRepositoryImpl(get(), get()) 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/walletconnection/model/AnswerChallengeRequest.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.walletconnection.model 2 | 3 | import kotlinx.serialization.Contextual 4 | import kotlinx.serialization.Serializable 5 | import java.util.UUID 6 | 7 | @Serializable 8 | data class AnswerChallengeRequest( 9 | @Contextual 10 | val challengeId: UUID, 11 | // data_signature or cbor (depending on GenerateChallengeRequest.method) 12 | val payload: String, 13 | // key only needed if method = SignedData 14 | val key: String? = null 15 | ) 16 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/walletconnection/model/AnswerChallengeResponse.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.walletconnection.model 2 | 3 | import kotlinx.serialization.Contextual 4 | import kotlinx.serialization.Serializable 5 | import java.time.LocalDateTime 6 | import java.util.UUID 7 | 8 | @Serializable 9 | data class AnswerChallengeResponse( 10 | @Contextual 11 | val connectionId: UUID, 12 | @Contextual 13 | val expiresAt: LocalDateTime 14 | ) 15 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/walletconnection/model/ChallengeMethod.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.walletconnection.model 2 | 3 | enum class ChallengeMethod { 4 | SignedData, 5 | SignedTransaction 6 | } 7 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/walletconnection/model/GenerateChallengeRequest.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.walletconnection.model 2 | 3 | import io.newm.chain.grpc.Utxo 4 | import io.newm.server.ktx.cborHexToUtxos 5 | import kotlinx.serialization.Serializable 6 | 7 | @Serializable 8 | data class GenerateChallengeRequest( 9 | val method: ChallengeMethod, 10 | val stakeAddress: String, 11 | // UTXOs and change address only needed if method = SignedTransaction 12 | val utxoCborHexList: List? = null, 13 | val changeAddress: String? = null, 14 | ) { 15 | val utxos: List by lazy { utxoCborHexList.cborHexToUtxos() } 16 | } 17 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/walletconnection/model/GenerateChallengeResponse.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.walletconnection.model 2 | 3 | import kotlinx.serialization.Contextual 4 | import kotlinx.serialization.Serializable 5 | import java.time.LocalDateTime 6 | import java.util.UUID 7 | 8 | @Serializable 9 | data class GenerateChallengeResponse( 10 | @Contextual 11 | val challengeId: UUID, 12 | @Contextual 13 | val expiresAt: LocalDateTime, 14 | // hex_string(data) or cbor(transaction) to be signed by requester (depending on GenerateChallengeRequest.method) 15 | val payload: String 16 | ) 17 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/features/walletconnection/model/WalletConnection.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.walletconnection.model 2 | 3 | import kotlinx.serialization.Contextual 4 | import kotlinx.serialization.Serializable 5 | import java.time.LocalDateTime 6 | import java.util.UUID 7 | 8 | @Serializable 9 | data class WalletConnection( 10 | @Contextual 11 | val id: UUID, 12 | @Contextual 13 | val createdAt: LocalDateTime, 14 | val stakeAddress: String 15 | ) 16 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/forwarder/ForwarderInstall.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.forwarder 2 | 3 | import io.ktor.server.application.Application 4 | import io.ktor.server.application.install 5 | import io.ktor.server.plugins.forwardedheaders.XForwardedHeaders 6 | 7 | fun Application.installForwarder() { 8 | install(XForwardedHeaders) 9 | } 10 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/ktx/AnyExt.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.ktx 2 | 3 | import io.newm.shared.exception.HttpBadRequestException 4 | 5 | fun T?.asMandatoryField(name: String): T { 6 | if (this == null) throw HttpBadRequestException("Missing required field: $name") 7 | return this 8 | } 9 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/ktx/ApplicationRequestExt.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.ktx 2 | 3 | import io.ktor.server.request.ApplicationRequest 4 | import io.newm.shared.exception.HttpBadRequestException 5 | 6 | fun ApplicationRequest.requiredHeader(name: String): String = headers[name] ?: throw HttpBadRequestException("Missing header: $name") 7 | 8 | fun ApplicationRequest.requiredQueryParam(name: String): String = queryParameters[name] ?: throw HttpBadRequestException("Missing query param: $name") 9 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/ktx/HttpClientExt.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.ktx 2 | 3 | import io.ktor.client.HttpClient 4 | import io.ktor.client.request.head 5 | import io.ktor.client.statement.HttpResponse 6 | 7 | suspend fun HttpClient.getFileSize(url: String): Long { 8 | val response: HttpResponse = head(url) 9 | return response.headers["Content-Length"]?.toLongOrNull() ?: 0L 10 | } 11 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/ktx/HttpResponseExt.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.ktx 2 | 3 | import io.ktor.client.call.body 4 | import io.ktor.client.statement.HttpResponse 5 | import io.ktor.client.statement.bodyAsText 6 | import io.ktor.http.isSuccess 7 | import io.newm.shared.exception.HttpStatusException.Companion.toException 8 | 9 | suspend inline fun HttpResponse.checkedBody(): T { 10 | if (!status.isSuccess()) throw status.toException(bodyAsText()) 11 | return body() 12 | } 13 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/ktx/JwtProviderExt.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.ktx 2 | 3 | import com.auth0.jwk.JwkProvider 4 | import com.auth0.jwt.interfaces.RSAKeyProvider 5 | import java.security.interfaces.RSAPrivateKey 6 | import java.security.interfaces.RSAPublicKey 7 | 8 | fun JwkProvider.toRSAKeyProvider(): RSAKeyProvider = 9 | object : RSAKeyProvider { 10 | override fun getPublicKeyById(keyId: String): RSAPublicKey = get(keyId).publicKey as RSAPublicKey 11 | 12 | override fun getPrivateKey(): RSAPrivateKey? = null 13 | 14 | override fun getPrivateKeyId(): String? = null 15 | } 16 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/ktx/KeyExt.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.ktx 2 | 3 | import com.google.protobuf.kotlin.toByteString 4 | import io.newm.chain.grpc.signingKey 5 | import io.newm.server.features.cardano.model.Key 6 | import io.newm.txbuilder.ktx.sign 7 | 8 | fun Key.sign(transactionId: ByteArray): ByteArray = 9 | signingKey { 10 | vkey = this@sign.vkey.toByteString() 11 | skey = this@sign.skey.toByteString() 12 | }.sign(transactionId) 13 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/ktx/VerificationExt.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.ktx 2 | 3 | import com.auth0.jwt.interfaces.Verification 4 | 5 | fun Verification.withAnyOfIssuer(issuers: List): Verification = 6 | withClaim("iss") { claim, _ -> 7 | claim.asString() in issuers 8 | } 9 | 10 | fun Verification.withAnyOfAudience(audiences: List): Verification = withAnyOfAudience(*audiences.toTypedArray()) 11 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/logging/CallLoggingInstall.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.logging 2 | 3 | import io.ktor.server.application.Application 4 | import io.ktor.server.application.install 5 | import io.ktor.server.plugins.calllogging.CallLogging 6 | import org.slf4j.event.Level 7 | 8 | fun Application.installCallLogging() { 9 | install(CallLogging) { 10 | level = Level.DEBUG 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/logging/InitializeLogging.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.logging 2 | 3 | import io.ktor.server.application.Application 4 | import io.ktor.server.application.log 5 | import org.slf4j.MDC 6 | import software.amazon.awssdk.imds.Ec2MetadataClient 7 | 8 | fun Application.initializeLogging() { 9 | val instanceId = try { 10 | Ec2MetadataClient.create().use { ec2MetadataClient -> 11 | ec2MetadataClient.get("/latest/meta-data/instance-id").asString() 12 | } 13 | } catch (e: Throwable) { 14 | log.error("Failed to get instanceId from EC2MetadataUtils", e) 15 | "instanceId-unknown" 16 | } 17 | MDC.put("instanceId", instanceId) 18 | } 19 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/logging/RequestLogging.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.logging 2 | 3 | import io.newm.shared.koin.inject 4 | import io.newm.shared.ktx.info 5 | import kotlinx.serialization.encodeToString 6 | import kotlinx.serialization.json.Json 7 | import org.slf4j.Logger 8 | 9 | val json: Json by inject() 10 | 11 | inline fun T.logRequestJson(log: Logger): T { 12 | log.info { "Sending Request ${this!!::class.simpleName}: ${json.encodeToString(this)}" } 13 | return this 14 | } 15 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/logging/SentryInstall.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.logging 2 | 3 | import io.ktor.server.application.Application 4 | import io.newm.shared.ktx.getConfigString 5 | import io.sentry.Sentry 6 | 7 | fun Application.initializeSentry() { 8 | Sentry.init { options -> 9 | options.dsn = environment.getConfigString("sentry.dsn") 10 | // options.tracesSampleRate = if (environment.developmentMode) 1.0 else 0.5 11 | options.tracesSampleRate = 1.0 12 | options.isDebug = developmentMode 13 | options.environment = environment.config.property("sentry.environment").getString() 14 | } 15 | } 16 | 17 | internal fun Throwable.captureToSentry() { 18 | Sentry.captureException(this) 19 | } 20 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/model/ClientPlatform.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.model 2 | 3 | enum class ClientPlatform { 4 | Studio, 5 | Android, 6 | IOS 7 | } 8 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/recaptcha/RecaptchaHeaders.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.recaptcha 2 | 3 | @Suppress("ktlint:standard:property-naming") 4 | object RecaptchaHeaders { 5 | const val Platform = "g-recaptcha-platform" 6 | const val Token = "g-recaptcha-token" 7 | } 8 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/recaptcha/RecaptchaKoinModule.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.recaptcha 2 | 3 | import io.newm.server.recaptcha.repo.RecaptchaRepository 4 | import io.newm.server.recaptcha.repo.RecaptchaRepositoryImpl 5 | import org.koin.dsl.module 6 | 7 | val recaptchaKoinModule = 8 | module { 9 | single { RecaptchaRepositoryImpl(get(), get(), get(), get()) } 10 | } 11 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/recaptcha/model/RecaptchaAssessmentRequest.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.recaptcha.model 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class RecaptchaAssessmentRequest( 8 | @SerialName("event") 9 | val event: Event 10 | ) { 11 | @Serializable 12 | data class Event( 13 | @SerialName("siteKey") 14 | val siteKey: String, 15 | @SerialName("token") 16 | val token: String 17 | ) 18 | } 19 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/recaptcha/repo/RecaptchaRepository.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.recaptcha.repo 2 | 3 | import io.ktor.server.request.ApplicationRequest 4 | import io.newm.shared.exception.HttpStatusException 5 | 6 | interface RecaptchaRepository { 7 | @Throws(HttpStatusException::class) 8 | suspend fun verify( 9 | action: String, 10 | request: ApplicationRequest 11 | ) 12 | } 13 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/security/KeyParser.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.security 2 | 3 | import io.ktor.util.decodeBase64Bytes 4 | 5 | object KeyParser { 6 | fun parse(key: String): ByteArray { 7 | // Remove the header and footer lines from the private key string 8 | val base64Key = 9 | key 10 | .replace(headerFooterRegexPattern, "") 11 | .replace(whitespaceRegexPattern, "") 12 | 13 | return base64Key.decodeBase64Bytes() 14 | } 15 | 16 | private val headerFooterRegexPattern = Regex("-----.*?-----") 17 | private val whitespaceRegexPattern = Regex("\\s") 18 | } 19 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/security/PrivateKeyReader.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.security 2 | 3 | import java.security.KeyFactory 4 | import java.security.PrivateKey 5 | import java.security.spec.PKCS8EncodedKeySpec 6 | 7 | object PrivateKeyReader { 8 | fun readFromString(privateKey: String): PrivateKey { 9 | val keyBytes = KeyParser.parse(privateKey) 10 | val keySpec = PKCS8EncodedKeySpec(keyBytes) 11 | return KeyFactory.getInstance("RSA").generatePrivate(keySpec) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/staticcontent/StaticContentRoutes.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.staticcontent 2 | 3 | import io.ktor.server.http.content.staticResources 4 | import io.ktor.server.routing.Routing 5 | 6 | fun Routing.createStaticContentRoutes() { 7 | staticResources(remotePath = "/contents", basePackage = "static") 8 | } 9 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/statuspages/StatusResponse.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.statuspages 2 | 3 | import kotlinx.serialization.Serializable 4 | 5 | @Serializable 6 | data class StatusResponse( 7 | val code: Int, 8 | val description: String, 9 | val cause: String 10 | ) 11 | -------------------------------------------------------------------------------- /newm-server/src/main/kotlin/io/newm/server/typealiases/TypeAliases.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.typealiases 2 | 3 | import java.util.UUID 4 | 5 | typealias SongId = UUID 6 | 7 | // ownerId, userId, requesterId 8 | typealias UserId = UUID 9 | 10 | typealias ReleaseId = UUID 11 | 12 | typealias SaleId = UUID 13 | 14 | typealias PurchaseId = UUID 15 | 16 | typealias PendingOrderId = UUID 17 | 18 | typealias PendingSaleId = UUID 19 | 20 | typealias BookmarkId = String 21 | -------------------------------------------------------------------------------- /newm-server/src/main/mjml/readme.txt: -------------------------------------------------------------------------------- 1 | MJML Readme 2 | ----------- 3 | 4 | We use MJML to efficiently generate responsive HTML emails (see https://mjml.io). Specifically, 5 | the .mjml files under the "mjml/email" directory are used to generate the .html files under the 6 | "resources/email" directory. 7 | 8 | Getting Started: 9 | 10 | 1) Learn MJML: https://documentation.mjml.io 11 | 12 | 2) Recommended tools: Visual Studio Code (https://code.visualstudio.com) with MJML Plugin 13 | for WYSIWYG editing and syntax error highlighting 14 | (https://marketplace.visualstudio.com/items?itemName=mjmlio.vscode-mjml) 15 | 16 | 3) Compile MJML to HTML: https://mjml.io/try-it-live (select "Minify HTML"). 17 | 18 | 4) Never modify .html files directly. 19 | -------------------------------------------------------------------------------- /newm-server/src/main/resources/audio-mime-types.properties: -------------------------------------------------------------------------------- 1 | # 2 | # Supported Audio MIME Types mapped to file extensions 3 | # 4 | audio/vnd.wave = wav 5 | audio/x-flac = flac 6 | audio/x-aiff = aiff 7 | -------------------------------------------------------------------------------- /newm-server/src/main/resources/email/arweave-warning.html: -------------------------------------------------------------------------------- 1 |

The Arweave Wallet balance is running low. Current balance is {balance} AR.

-------------------------------------------------------------------------------- /newm-server/src/main/resources/images/qrcode-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectNEWM/newm-server/a96fc7499e5b2610bbb66cc1a305b26fa86ec2b0/newm-server/src/main/resources/images/qrcode-logo.png -------------------------------------------------------------------------------- /newm-server/src/main/resources/monitor_orders_quartz.properties: -------------------------------------------------------------------------------- 1 | org.quartz.scheduler.instanceId = AUTO 2 | org.quartz.scheduler.instanceName = ClaimOrdersScheduler 3 | org.quartz.threadPool.threadCount = 50 4 | org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX 5 | org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.PostgreSQLDelegate 6 | org.quartz.jobStore.tablePrefix = QRTZ_ 7 | org.quartz.jobStore.dataSource = newmServerDatasource 8 | org.quartz.jobStore.isClustered = true 9 | org.quartz.jobStore.clusterCheckinInterval = 30000 10 | org.quartz.dataSource.newmServerDatasource.connectionProvider.class = io.newm.server.features.scheduler.SchedulerPoolingConnectionProvider 11 | org.quartz.scheduler.batchTriggerAcquisitionFireAheadTimeWindow = 10000 -------------------------------------------------------------------------------- /newm-server/src/main/resources/quartz.properties: -------------------------------------------------------------------------------- 1 | org.quartz.scheduler.instanceId = AUTO 2 | org.quartz.scheduler.instanceName = NewmServerScheduler 3 | org.quartz.threadPool.threadCount = 1 4 | org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX 5 | org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.PostgreSQLDelegate 6 | org.quartz.jobStore.tablePrefix = QRTZ_ 7 | org.quartz.jobStore.dataSource = newmServerDatasource 8 | org.quartz.jobStore.isClustered = true 9 | org.quartz.jobStore.clusterCheckinInterval = 30000 10 | org.quartz.dataSource.newmServerDatasource.connectionProvider.class = io.newm.server.features.scheduler.SchedulerPoolingConnectionProvider 11 | org.quartz.scheduler.batchTriggerAcquisitionFireAheadTimeWindow = 10000 12 | -------------------------------------------------------------------------------- /newm-server/src/main/resources/static/predefined-moods.json: -------------------------------------------------------------------------------- 1 | [ 2 | "Aggressive", 3 | "Brooding", 4 | "Cool", 5 | "Defiant", 6 | "Easygoing", 7 | "Empowering", 8 | "Energizing", 9 | "Excited", 10 | "Fiery", 11 | "Gritty", 12 | "Melancholy", 13 | "Other", 14 | "Peaceful", 15 | "Romantic", 16 | "Rowdy", 17 | "Sensual", 18 | "Sentimental", 19 | "Serious", 20 | "Sophisticated", 21 | "Stirring", 22 | "Tender", 23 | "Upbeat", 24 | "Yearning" 25 | ] 26 | -------------------------------------------------------------------------------- /newm-server/src/main/resources/static/stream-token-policy-ids.json: -------------------------------------------------------------------------------- 1 | [ 2 | "46e607b3046a34c95e7c29e47047618dbf5e10de777ba56c590cfd5c", 3 | "3333c8022c24d2014f02236c082105ebceb73c46c45f94eb99136f92" 4 | ] 5 | -------------------------------------------------------------------------------- /newm-server/src/test/kotlin/io/newm/server/features/earnings/EarningsTest.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.earnings 2 | 3 | import com.google.common.truth.Truth.assertThat 4 | import org.junit.jupiter.api.Test 5 | 6 | class EarningsTest { 7 | @Test 8 | fun `test BigDecimal earnings math`() { 9 | val totalNewmAmount = 250000000000.toBigDecimal() 10 | val totalSupply = 100_000_000.toBigDecimal() 11 | val streamTokenAmount = 50000000.toBigDecimal() 12 | val royalties = (totalNewmAmount * (streamTokenAmount.setScale(6) / totalSupply.setScale(6))).toLong() 13 | assertThat(royalties).isEqualTo(125000000000L) 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /newm-server/src/test/kotlin/io/newm/server/features/playlist/TestPlaylists.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.features.playlist 2 | 3 | import io.newm.server.features.playlist.model.Playlist 4 | 5 | val testPlaylist1 = 6 | Playlist( 7 | name = "Test Playlist 1" 8 | ) 9 | 10 | val testPlaylist2 = 11 | Playlist( 12 | name = "Test Playlist 2" 13 | ) 14 | 15 | val testPlaylist3 = 16 | Playlist( 17 | name = "Test Playlist 3" 18 | ) 19 | 20 | val testPlaylists = listOf(testPlaylist1, testPlaylist2, testPlaylist3) 21 | -------------------------------------------------------------------------------- /newm-server/src/test/kotlin/io/newm/server/utils/ResourceOutgoingContent.kt: -------------------------------------------------------------------------------- 1 | package io.newm.server.utils 2 | 3 | import io.ktor.http.content.OutgoingContent 4 | import io.ktor.utils.io.ByteWriteChannel 5 | import io.ktor.utils.io.jvm.javaio.toOutputStream 6 | 7 | class ResourceOutgoingContent( 8 | private val name: String 9 | ) : OutgoingContent.WriteChannelContent() { 10 | override suspend fun writeTo(channel: ByteWriteChannel) { 11 | ClassLoader.getSystemResourceAsStream(name)!!.use { input -> 12 | channel.toOutputStream().use { output -> 13 | input.copyTo(output) 14 | } 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /newm-server/src/test/resources/sample1.flac: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectNEWM/newm-server/a96fc7499e5b2610bbb66cc1a305b26fa86ec2b0/newm-server/src/test/resources/sample1.flac -------------------------------------------------------------------------------- /newm-shared/src/main/kotlin/io/newm/shared/auth/Password.kt: -------------------------------------------------------------------------------- 1 | package io.newm.shared.auth 2 | 3 | import io.newm.shared.ktx.toHash 4 | import io.newm.shared.ktx.verify 5 | import io.newm.shared.serialization.PasswordSerializer 6 | import kotlinx.serialization.Serializable 7 | 8 | @Serializable(with = PasswordSerializer::class) 9 | data class Password( 10 | val value: String 11 | ) { 12 | override fun toString(): String = if (value.isBlank()) value else "***" 13 | 14 | fun toHash(): String = value.toHash() 15 | 16 | fun verify(hash: String): Boolean = value.verify(hash) 17 | } 18 | -------------------------------------------------------------------------------- /newm-shared/src/main/kotlin/io/newm/shared/daemon/DaemonInstall.kt: -------------------------------------------------------------------------------- 1 | package io.newm.shared.daemon 2 | 3 | import io.ktor.server.application.Application 4 | import io.ktor.server.application.ApplicationStopPreparing 5 | import org.koin.ktor.ext.getKoin 6 | 7 | fun Application.initializeDaemons() { 8 | val daemons = getKoin().getAll() 9 | 10 | // Add shutdown hook 11 | monitor.subscribe(ApplicationStopPreparing) { 12 | // Shutdown the Daemons 13 | daemons.forEach { daemon -> daemon.shutdown() } 14 | } 15 | 16 | daemons.forEach { it.start() } 17 | } 18 | -------------------------------------------------------------------------------- /newm-shared/src/main/kotlin/io/newm/shared/koin/Inject.kt: -------------------------------------------------------------------------------- 1 | package io.newm.shared.koin 2 | 3 | import org.koin.core.context.GlobalContext 4 | import org.koin.core.parameter.ParametersDefinition 5 | import org.koin.core.qualifier.Qualifier 6 | 7 | inline fun inject( 8 | qualifier: Qualifier? = null, 9 | noinline parameters: ParametersDefinition? = null 10 | ) = GlobalContext.get().inject(qualifier = qualifier, parameters = parameters) 11 | -------------------------------------------------------------------------------- /newm-shared/src/main/kotlin/io/newm/shared/ktx/BigDecimalExt.kt: -------------------------------------------------------------------------------- 1 | package io.newm.shared.ktx 2 | 3 | import java.math.BigDecimal 4 | import java.text.NumberFormat 5 | import java.util.Locale 6 | 7 | fun BigDecimal.toGroupingString(): String { 8 | val formatter = NumberFormat.getInstance(Locale.US).apply { 9 | isGroupingUsed = true 10 | maximumFractionDigits = scale() 11 | } 12 | return formatter.format(this) 13 | } 14 | 15 | fun BigDecimal?.orZero(): BigDecimal = this ?: BigDecimal.ZERO 16 | -------------------------------------------------------------------------------- /newm-shared/src/main/kotlin/io/newm/shared/ktx/ByteArrayExt.kt: -------------------------------------------------------------------------------- 1 | package io.newm.shared.ktx 2 | 3 | import java.util.HexFormat 4 | 5 | fun ByteArray.toHexString(): String = HexFormat.of().formatHex(this) 6 | -------------------------------------------------------------------------------- /newm-shared/src/main/kotlin/io/newm/shared/ktx/EntityClassExt.kt: -------------------------------------------------------------------------------- 1 | package io.newm.shared.ktx 2 | 3 | import org.jetbrains.exposed.dao.Entity 4 | import org.jetbrains.exposed.dao.EntityClass 5 | import org.jetbrains.exposed.sql.Op 6 | import org.jetbrains.exposed.sql.SqlExpressionBuilder 7 | 8 | fun , T : Entity> EntityClass.exists(op: SqlExpressionBuilder.() -> Op): Boolean = table.exists(op) 9 | 10 | fun , T : Entity> EntityClass.existsHavingId(id: ID): Boolean = table.existsHavingId(id) 11 | -------------------------------------------------------------------------------- /newm-shared/src/main/kotlin/io/newm/shared/ktx/InstantExt.kt: -------------------------------------------------------------------------------- 1 | package io.newm.shared.ktx 2 | 3 | import java.time.Instant 4 | import java.util.Date 5 | 6 | fun Instant.toDate(): Date = Date.from(this) 7 | -------------------------------------------------------------------------------- /newm-shared/src/main/kotlin/io/newm/shared/ktx/IntExt.kt: -------------------------------------------------------------------------------- 1 | package io.newm.shared.ktx 2 | 3 | fun Int?.orZero(): Int = this ?: 0 4 | -------------------------------------------------------------------------------- /newm-shared/src/main/kotlin/io/newm/shared/ktx/JsonPrimitiveExt.kt: -------------------------------------------------------------------------------- 1 | package io.newm.shared.ktx 2 | 3 | import kotlinx.serialization.json.JsonPrimitive 4 | import kotlinx.serialization.json.booleanOrNull 5 | import kotlinx.serialization.json.double 6 | import kotlinx.serialization.json.longOrNull 7 | 8 | val JsonPrimitive.value: Any 9 | get() = if (isString) content else booleanOrNull ?: longOrNull ?: double 10 | -------------------------------------------------------------------------------- /newm-shared/src/main/kotlin/io/newm/shared/ktx/LazyExt.kt: -------------------------------------------------------------------------------- 1 | package io.newm.shared.ktx 2 | 3 | import kotlinx.coroutines.runBlocking 4 | 5 | inline fun coLazy(crossinline initializer: suspend () -> T): Lazy = lazy { runBlocking { initializer() } } 6 | -------------------------------------------------------------------------------- /newm-shared/src/main/kotlin/io/newm/shared/ktx/ListExt.kt: -------------------------------------------------------------------------------- 1 | package io.newm.shared.ktx 2 | 3 | fun List.containsIgnoreCase(element: String?): Boolean = this.any { it.equals(element, ignoreCase = true) } 4 | -------------------------------------------------------------------------------- /newm-shared/src/main/kotlin/io/newm/shared/ktx/LocalDateTimeExt.kt: -------------------------------------------------------------------------------- 1 | package io.newm.shared.ktx 2 | 3 | import java.time.LocalDateTime 4 | import java.time.ZoneId 5 | import java.util.Date 6 | 7 | fun LocalDateTime.toDate(): Date = atZone(ZoneId.systemDefault()).toInstant().toDate() 8 | -------------------------------------------------------------------------------- /newm-shared/src/main/kotlin/io/newm/shared/ktx/PropertiesExt.kt: -------------------------------------------------------------------------------- 1 | package io.newm.shared.ktx 2 | 3 | import java.util.Properties 4 | 5 | fun propertiesFromResource(name: String): Properties = 6 | ClassLoader.getSystemResourceAsStream(name).use { stream -> 7 | Properties().apply { load(stream) } 8 | } 9 | -------------------------------------------------------------------------------- /newm-shared/src/main/kotlin/io/newm/shared/ktx/SecureRandomExt.kt: -------------------------------------------------------------------------------- 1 | package io.newm.shared.ktx 2 | 3 | import java.security.SecureRandom 4 | import kotlin.math.pow 5 | 6 | fun SecureRandom.nextDigitCode(size: Int): String = nextLong(10.0.pow(size).toLong()).toString().padStart(size, '0') 7 | -------------------------------------------------------------------------------- /newm-shared/src/main/kotlin/io/newm/shared/test/TestUtils.kt: -------------------------------------------------------------------------------- 1 | package io.newm.shared.test 2 | 3 | object TestUtils { 4 | fun isRunningInTest(): Boolean = 5 | try { 6 | Class.forName("org.junit.jupiter.api.Test") 7 | true 8 | } catch (e: ClassNotFoundException) { 9 | false 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /newm-tx-builder/src/main/kotlin/io/newm/txbuilder/ktx/CardanoEraKtx.kt: -------------------------------------------------------------------------------- 1 | package io.newm.txbuilder.ktx 2 | 3 | import com.google.iot.cbor.CborTag 4 | import io.newm.kogmios.protocols.model.CardanoEra 5 | 6 | fun CardanoEra.toSetTag(): Int = 7 | when (this) { 8 | CardanoEra.CONWAY -> 258 9 | else -> CborTag.UNTAGGED 10 | } 11 | -------------------------------------------------------------------------------- /newm-tx-builder/src/test/resources/.gitignore: -------------------------------------------------------------------------------- 1 | contract_chaining_preprod_test.addr 2 | contract_chaining_preprod_test.skey 3 | contract_chaining_preprod_test.vkey 4 | -------------------------------------------------------------------------------- /settings.gradle.kts: -------------------------------------------------------------------------------- 1 | rootProject.name = "newm-server" 2 | include("newm-server") 3 | include("newm-chain") 4 | include("newm-chain-db") 5 | include("newm-chain-grpc") 6 | include("ktor-grpc") 7 | include("newm-objectpool") 8 | include("newm-shared") 9 | include("newm-tx-builder") 10 | include("newm-chain-util") 11 | -------------------------------------------------------------------------------- /system.properties: -------------------------------------------------------------------------------- 1 | java.runtime.version=21 2 | --------------------------------------------------------------------------------