diff --git a/apps/frontend/src/app/app.routes.ts b/apps/frontend/src/app/app.routes.ts index 7ea7dbc..2d89f60 100644 --- a/apps/frontend/src/app/app.routes.ts +++ b/apps/frontend/src/app/app.routes.ts @@ -4,6 +4,7 @@ import { AboutComponent } from './features/about/about.component' import { LoginComponent } from './features/login/login.component' import { RegisterComponent } from './features/register/register.component' import { AuthGuard } from './guards/auth.guard' +import { CastComponent } from './features/voting/cast/cast.component' export const appRoutes: Route[] = [ { @@ -25,7 +26,31 @@ export const appRoutes: Route[] = [ component: RegisterComponent, }, { - path: '**', + path: 'voting', + children: [ + { + path: 'cast', + children: [ + { + path: '', + redirectTo: '/', + pathMatch: 'full', + }, + { + path: ':id', + component: CastComponent, + }, + ], + }, + { + path: '', + redirectTo: '/', + pathMatch: 'full', + }, + ], + }, + { + path: 'about', redirectTo: '', }, ] diff --git a/apps/frontend/src/app/config/config.ts b/apps/frontend/src/app/config/config.ts index e7e1ef1..03c42ae 100644 --- a/apps/frontend/src/app/config/config.ts +++ b/apps/frontend/src/app/config/config.ts @@ -1,5 +1,6 @@ import * as process from 'process' -const API_URL = process.env.API_URL || 'http://localhost:3000' - -export { API_URL } +const API_URL = process.env['API_URL'] || 'http://localhost:3000' +const CONTRACT_ID = process.env['CONTRACT_ID'] || '' +const TEST_ACCOUNT = process.env['TEST_ACCOUNT'] || '' +export { API_URL, CONTRACT_ID, TEST_ACCOUNT } diff --git a/apps/frontend/src/app/core/stellar/castVote.service.ts b/apps/frontend/src/app/core/stellar/castVote.service.ts new file mode 100644 index 0000000..89a70ae --- /dev/null +++ b/apps/frontend/src/app/core/stellar/castVote.service.ts @@ -0,0 +1,83 @@ +import { Injectable } from '@angular/core' +import { CONTRACT_ID } from '../../config/config' +import { + BASE_FEE, + Contract, + nativeToScVal, + Networks, + SorobanRpc, + TransactionBuilder, +} from '@stellar/stellar-sdk' +import { Keypair } from '@stellar/typescript-wallet-sdk' + +@Injectable({ + providedIn: 'root', +}) +export class CastVoteService { + private contractId = CONTRACT_ID + private isLoading = true + private hasError = false + private errorMessage = '' + + async castVote( + server: SorobanRpc.Server, + sourceKeypair: Keypair, + voteId: string, + currentOption: string, + ) { + try { + const contract = new Contract(this.contractId) + + const sourceAccount = await server.getAccount(sourceKeypair.publicKey()) + + const builtTransaction = new TransactionBuilder(sourceAccount, { + fee: BASE_FEE, + networkPassphrase: Networks.TESTNET, + }) + .addOperation( + contract.call( + 'cast', + nativeToScVal(voteId, { type: 'symbol' }), + nativeToScVal(currentOption, { type: 'symbol' }), + nativeToScVal(sourceKeypair.publicKey(), { type: 'address' }), + ), + ) + .setTimeout(30) + .build() + + const preparedTransaction = await server.prepareTransaction( + builtTransaction, + ) + + preparedTransaction.sign(sourceKeypair) + + const sendResponse = await server.sendTransaction(preparedTransaction) + + if (sendResponse.status === 'PENDING') { + let getResponse = await server.getTransaction(sendResponse.hash) + while (getResponse.status === 'NOT_FOUND') { + await new Promise(resolve => setTimeout(resolve, 1000)) + getResponse = await server.getTransaction(sendResponse.hash) + } + if (getResponse.status === 'SUCCESS') { + this.isLoading = false + } else { + return + } + } else { + return + } + } catch (err) { + this.isLoading = false + this.hasError = true + this.errorMessage = + 'There was an Error submitting your vote, did you vote already?' + } + + return { + isLoading: this.isLoading, + hasError: this.hasError, + errorMessage: this.errorMessage, + } + } +} diff --git a/apps/frontend/src/app/core/stellar/getVoteOption.service.ts b/apps/frontend/src/app/core/stellar/getVoteOption.service.ts new file mode 100644 index 0000000..2cab911 --- /dev/null +++ b/apps/frontend/src/app/core/stellar/getVoteOption.service.ts @@ -0,0 +1,91 @@ +import { Injectable } from '@angular/core' +import { CONTRACT_ID } from '../../config/config' +import { + BASE_FEE, + Contract, + nativeToScVal, + Networks, + SorobanRpc, + TransactionBuilder, +} from '@stellar/stellar-sdk' +import { Keypair } from '@stellar/typescript-wallet-sdk' + +@Injectable({ + providedIn: 'root', +}) +export class GetVoteOptionService { + private contractId = CONTRACT_ID + private optionsArr = new Array() + private isLoading = true + private hasError = false + private errorMessage = '' + + async getVoteOptions( + server: SorobanRpc.Server, + sourceKeypair: Keypair, + voteId: string, + ) { + try { + const contract = new Contract(this.contractId) + + const sourceAccount = await server.getAccount(sourceKeypair.publicKey()) + + const builtTransaction = new TransactionBuilder(sourceAccount, { + fee: BASE_FEE, + networkPassphrase: Networks.TESTNET, + }) + .addOperation( + contract.call( + 'get_vote_options', + nativeToScVal(voteId, { type: 'symbol' }), + ), + ) + .setTimeout(30) + .build() + + const preparedTransaction = await server.prepareTransaction( + builtTransaction, + ) + + preparedTransaction.sign(sourceKeypair) + + const sendResponse = await server.sendTransaction(preparedTransaction) + + if (sendResponse.status === 'PENDING') { + let getResponse = await server.getTransaction(sendResponse.hash) + while (getResponse.status === 'NOT_FOUND') { + await new Promise(resolve => setTimeout(resolve, 1000)) + getResponse = await server.getTransaction(sendResponse.hash) + } + if (getResponse.status === 'SUCCESS') { + if (!getResponse.returnValue?.vec()) { + return + } + + getResponse.returnValue.vec()?.forEach(item => { + if (!item.value()) { + return + } + this.optionsArr.push(String(item.value())) + }) + this.isLoading = false + } else { + return + } + } else { + return + } + } catch (err) { + this.isLoading = false + this.hasError = true + this.errorMessage = + 'There was an Error getting this vote ID, please try again.' + } + return { + optionsArr: this.optionsArr, + isLoading: this.isLoading, + hasError: this.hasError, + errorMessage: this.errorMessage, + } + } +} diff --git a/apps/frontend/src/app/features/register/register.component.ts b/apps/frontend/src/app/features/register/register.component.ts index 5f9e015..b2bc6aa 100644 --- a/apps/frontend/src/app/features/register/register.component.ts +++ b/apps/frontend/src/app/features/register/register.component.ts @@ -12,13 +12,13 @@ import { Keypair } from '@stellar/typescript-wallet-sdk' styleUrls: ['./register.component.css'], }) export class RegisterComponent { - publicKey: string = '' - secretKey: string = '' - captchaImage: string = '' - captchaId: string = '' - transaction: string = '' - captchaAnswer: string = '' - authToken: string = '' + publicKey = '' + secretKey = '' + captchaImage = '' + captchaId = '' + transaction = '' + captchaAnswer = '' + authToken = '' constructor(private authService: AuthService) {} diff --git a/apps/frontend/src/app/features/voting/cast/cast.component.css b/apps/frontend/src/app/features/voting/cast/cast.component.css new file mode 100644 index 0000000..e69de29 diff --git a/apps/frontend/src/app/features/voting/cast/cast.component.html b/apps/frontend/src/app/features/voting/cast/cast.component.html new file mode 100644 index 0000000..1c940a0 --- /dev/null +++ b/apps/frontend/src/app/features/voting/cast/cast.component.html @@ -0,0 +1,83 @@ +
+
+ @if(isLoading){ +
+ + Loading... +
+ } @if (!isLoading && !hasError){ @for (option of optionsArr; track option){ +
+ +
+ } + + } @if (hasError){ +
+
+
+ +
+
+

An Error Occurred

+
+

{{ errorMessage }}

+
+
+
+
+ + } +
+
diff --git a/apps/frontend/src/app/features/voting/cast/cast.component.spec.ts b/apps/frontend/src/app/features/voting/cast/cast.component.spec.ts new file mode 100644 index 0000000..8d80aed --- /dev/null +++ b/apps/frontend/src/app/features/voting/cast/cast.component.spec.ts @@ -0,0 +1,22 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing' + +import { CastComponent } from './cast.component' + +describe('CastComponent', () => { + let component: CastComponent + let fixture: ComponentFixture + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [CastComponent], + }).compileComponents() + + fixture = TestBed.createComponent(CastComponent) + component = fixture.componentInstance + fixture.detectChanges() + }) + + it('should create', () => { + expect(component).toBeTruthy() + }) +}) diff --git a/apps/frontend/src/app/features/voting/cast/cast.component.ts b/apps/frontend/src/app/features/voting/cast/cast.component.ts new file mode 100644 index 0000000..343141c --- /dev/null +++ b/apps/frontend/src/app/features/voting/cast/cast.component.ts @@ -0,0 +1,96 @@ +import { Component, OnInit } from '@angular/core' +import { Keypair, SorobanRpc } from '@stellar/stellar-sdk' +import { ActivatedRoute } from '@angular/router' +import { Location } from '@angular/common' +import { GetVoteOptionService } from '../../../core/stellar/getVoteOption.service' +import { CastVoteService } from '../../../core/stellar/castVote.service' +import { TEST_ACCOUNT } from '../../../config/config' + +@Component({ + selector: 'app-cast', + standalone: true, + imports: [], + templateUrl: './cast.component.html', + styleUrl: './cast.component.css', +}) +export class CastComponent implements OnInit { + sourceKeypair = Keypair.fromSecret(TEST_ACCOUNT) + + server = new SorobanRpc.Server('https://soroban-testnet.stellar.org') + + voteId = '' + currentOption = '' + optionsArr = new Array() + isLoading = true + + hasError = false + errorMessage = '' + + constructor( + private route: ActivatedRoute, + private location: Location, + private getVoteOptionService: GetVoteOptionService, + private castVoteService: CastVoteService, + ) {} + + async ngOnInit() { + this.route.params.subscribe(params => { + this.voteId = params['id'] + }) + await this.getVoteOptions() + } + + async getVoteOptions() { + this.isLoading = true + const result = await this.getVoteOptionService.getVoteOptions( + this.server, + this.sourceKeypair, + this.voteId, + ) + if ( + result?.errorMessage === undefined || + result?.hasError === undefined || + result?.optionsArr === undefined || + result?.isLoading === undefined + ) { + this.isLoading = false + this.hasError = true + this.errorMessage = 'An unexpected Error occurred' + return + } + + this.optionsArr = result.optionsArr + this.isLoading = result.isLoading + this.hasError = result.hasError + this.errorMessage = result.errorMessage + } + + async submitVote() { + this.isLoading = true + const result = await this.castVoteService.castVote( + this.server, + this.sourceKeypair, + this.voteId, + this.currentOption, + ) + + if ( + result?.errorMessage === undefined || + result?.hasError === undefined || + result?.isLoading === undefined + ) { + this.isLoading = false + this.hasError = true + this.errorMessage = 'An unexpected Error occurred' + return + } + + this.isLoading = result.isLoading + this.hasError = result.hasError + this.errorMessage = result.errorMessage + } + + goBack() { + this.location.back() + } +} diff --git a/contracts/VotingContract/README.md b/contracts/VotingContract/README.md index d8dc1ee..5f58c60 100644 --- a/contracts/VotingContract/README.md +++ b/contracts/VotingContract/README.md @@ -52,7 +52,7 @@ stellar contract invoke \ --source {local-stellar-user} \ --network {stellar-network} \ -- \ - create_vote --vote_id {vote-id} --options '[{vote1}, {vote2}, {...}]' --title {vote-title} --description {vote-description} --start_date '"{start-date-nr (ddMMYYYY)}"' --end_date '"{end-date-nr (ddMMYYYY)}"' + create_vote --vote_id {vote-id} --vote_options '[{vote1}, {vote2}, {...}]' --title {vote-title} --description {vote-description} --start_date '"{start-date-nr (ddMMYYYY)}"' --end_date '"{end-date-nr (ddMMYYYY)}"' ```
example
@@ -63,7 +63,7 @@ stellar contract invoke \ --source grill \ --network testnet \ -- \ - create_vote --vote_id testvote --options '["Trump", "Harris"]' --title TestTitle --description Beschreibung --start_date '"25072024"' --end_date '"26072024"' + create_vote --vote_id testvote --vote_options '["Trump", "Harris"]' --title TestTitle --description Beschreibung --start_date '"25072024"' --end_date '"26072024"' ```
result
@@ -156,8 +156,24 @@ stellar contract invoke \ get_vote_result --vote_id testvote ``` -
result
+## deploy_ts + +
theory
+ +``` +stellar contract bindings typescript \ + --network {stellar-network} \ + --contract-id {contract-id} \ + --output-dir ../../packages/voting_contract \ + --overwrite +``` + +
example
``` -{"\"Harris\"":0,"\"Trump\"":1} +stellar contract bindings typescript \ + --network testnet \ + --contract-id CAFM6NNXNSR2ST7EANC4R6EJZ6NUMFGP6EA2RRGXLUCYXPRHHTB36WU2 \ + --output-dir ../../packages/voting_contract \ + --overwrite ``` diff --git a/contracts/VotingContract/src/lib.rs b/contracts/VotingContract/src/lib.rs index 02b3538..1d5a9d7 100644 --- a/contracts/VotingContract/src/lib.rs +++ b/contracts/VotingContract/src/lib.rs @@ -10,14 +10,14 @@ impl VotingContract { pub fn create_vote( env: Env, vote_id: Symbol, - options: Vec, + vote_options: Vec, title: String, description: String, start_date: String, end_date: String, ) { let mut options_map = Map::new(&env); - for option in options.iter() { + for option in vote_options.iter() { options_map.set(option, 0u32); } @@ -36,6 +36,11 @@ impl VotingContract { vec![&env, title, description, start_date, end_date] } + pub fn get_vote_options(env: Env, vote_id: Symbol) -> Vec { + let options_map: Map = env.storage().instance().get(&vote_id).unwrap(); + options_map.keys() + } + pub fn cast(env: Env, vote_id: Symbol, option: Symbol, voter: Address) { let mut options_map: Map = env.storage().instance().get(&vote_id).unwrap(); let has_casted_key = (vote_id.clone(), voter.clone()); diff --git a/contracts/VotingContract/src/test.rs b/contracts/VotingContract/src/test.rs index 340a3fe..edda97e 100644 --- a/contracts/VotingContract/src/test.rs +++ b/contracts/VotingContract/src/test.rs @@ -49,6 +49,29 @@ fn get_vote() { ) } +#[test] +fn get_vote_options() { + let env = Env::default(); + let contract_id = env.register_contract(None, VotingContract); + let client = VotingContractClient::new(&env, &contract_id); + + client.create_vote( + &symbol_short!("ID"), + &vec![&env, symbol_short!("OP1"), symbol_short!("OP2")], + &String::from_str(&env, "Title"), + &String::from_str(&env, "Desc"), + &String::from_str(&env, "0"), + &String::from_str(&env, "0"), + ); + + let options = client.get_vote_options(&symbol_short!("ID")); + + assert_eq!( + options, + vec![&env, symbol_short!("OP1"), symbol_short!("OP2")] + ); +} + #[test] fn vote() { let env = Env::default(); diff --git a/package-lock.json b/package-lock.json index b07009b..34d918b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -44,6 +44,7 @@ "reflect-metadata": "^0.1.13", "rxjs": "~7.8.0", "tslib": "^2.3.0", + "voting_contract": "./packages/voting_contract", "zone.js": "~0.14.3" }, "devDependencies": { @@ -30588,6 +30589,10 @@ "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==", "license": "MIT" }, + "node_modules/voting_contract": { + "resolved": "packages/voting_contract", + "link": true + }, "node_modules/w3c-xmlserializer": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz", @@ -31655,6 +31660,66 @@ "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.14.8.tgz", "integrity": "sha512-48uh7MnVp4/OQDuCHeFdXw5d8xwPqFTvlHgPJ1LBFb5GaustLSZV+YUH0to5ygNyGpqTsjpbpt141U/j3pCfqQ==", "license": "MIT" + }, + "packages/voting_contract": { + "version": "0.0.0", + "dependencies": { + "@stellar/stellar-sdk": "12.1.0", + "buffer": "6.0.3" + }, + "devDependencies": { + "typescript": "5.3.3" + } + }, + "packages/voting_contract/node_modules/@stellar/stellar-sdk": { + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/@stellar/stellar-sdk/-/stellar-sdk-12.1.0.tgz", + "integrity": "sha512-Va0hu9SaPezmMbO5eMwL5D15Wrx1AGWRtxayUDRWV2Fr3ynY58mvCZS1vsgNQ4kE8MZe3nBVKv6T9Kzqwgx1PQ==", + "dependencies": { + "@stellar/stellar-base": "^12.0.1", + "axios": "^1.7.2", + "bignumber.js": "^9.1.2", + "eventsource": "^2.0.2", + "randombytes": "^2.1.0", + "toml": "^3.0.0", + "urijs": "^1.19.1" + } + }, + "packages/voting_contract/node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "packages/voting_contract/node_modules/typescript": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", + "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } } } } diff --git a/package.json b/package.json index 6702d20..5898e2c 100644 --- a/package.json +++ b/package.json @@ -42,7 +42,8 @@ "reflect-metadata": "^0.1.13", "rxjs": "~7.8.0", "tslib": "^2.3.0", - "zone.js": "~0.14.3" + "zone.js": "~0.14.3", + "voting_contract": "./packages/voting_contract" }, "devDependencies": { "@angular-devkit/build-angular": "~18.1.0", diff --git a/packages/voting_contract/.gitignore b/packages/voting_contract/.gitignore new file mode 100644 index 0000000..72aae85 --- /dev/null +++ b/packages/voting_contract/.gitignore @@ -0,0 +1,2 @@ +node_modules/ +out/ diff --git a/packages/voting_contract/README.md b/packages/voting_contract/README.md new file mode 100644 index 0000000..4db8ae2 --- /dev/null +++ b/packages/voting_contract/README.md @@ -0,0 +1,54 @@ +# voting_contract JS + +JS library for interacting with [Soroban](https://soroban.stellar.org/) smart contract `voting_contract` via Soroban RPC. + +This library was automatically generated by Soroban CLI using a command similar to: + +```bash +soroban contract bindings ts \ + --rpc-url https://soroban-testnet.stellar.org:443 \ + --network-passphrase "Test SDF Network ; September 2015" \ + --contract-id CA6Z3UEZ6EH6VHKO2EEVDGOZI7CT4SATQP7HNTPWODL5OJSDRULXRJCG \ + --output-dir ./path/to/voting_contract +``` + +The network passphrase and contract ID are exported from [index.ts](./src/index.ts) in the `networks` constant. If you are the one who generated this library and you know that this contract is also deployed to other networks, feel free to update `networks` with other valid options. This will help your contract consumers use this library more easily. + +# To publish or not to publish + +This library is suitable for publishing to NPM. You can publish it to NPM using the `npm publish` command. + +But you don't need to publish this library to NPM to use it. You can add it to your project's `package.json` using a file path: + +```json +"dependencies": { + "voting_contract": "./path/to/this/folder" +} +``` + +However, we've actually encountered [frustration](https://github.com/stellar/soroban-example-dapp/pull/117#discussion_r1232873560) using local libraries with NPM in this way. Though it seems a bit messy, we suggest generating the library directly to your `node_modules` folder automatically after each install by using a `postinstall` script. We've had the least trouble with this approach. NPM will automatically remove what it sees as erroneous directories during the `install` step, and then regenerate them when it gets to your `postinstall` step, which will keep the library up-to-date with your contract. + +```json +"scripts": { + "postinstall": "soroban contract bindings ts --rpc-url https://soroban-testnet.stellar.org:443 --network-passphrase \"Test SDF Network ; September 2015\" --id CA6Z3UEZ6EH6VHKO2EEVDGOZI7CT4SATQP7HNTPWODL5OJSDRULXRJCG --name voting_contract" +} +``` + +Obviously you need to adjust the above command based on the actual command you used to generate the library. + +# Use it + +Now that you have your library up-to-date and added to your project, you can import it in a file and see inline documentation for all of its exported methods: + +```js +import { Contract, networks } from "voting_contract" + +const contract = new Contract({ + ...networks.futurenet, // for example; check which networks this library exports + rpcUrl: '...', // use your own, or find one for testing at https://soroban.stellar.org/docs/reference/rpc#public-rpc-providers +}) + +contract.| +``` + +As long as your editor is configured to show JavaScript/TypeScript documentation, you can pause your typing at that `|` to get a list of all exports and inline-documentation for each. It exports a separate [async](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function) function for each method in the smart contract, with documentation for each generated from the comments the contract's author included in the original source code. diff --git a/packages/voting_contract/package-lock.json b/packages/voting_contract/package-lock.json new file mode 100644 index 0000000..894b4f7 --- /dev/null +++ b/packages/voting_contract/package-lock.json @@ -0,0 +1,322 @@ +{ + "name": "voting_contract", + "version": "0.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "voting_contract", + "version": "0.0.0", + "dependencies": { + "@stellar/stellar-sdk": "12.1.0", + "buffer": "6.0.3" + }, + "devDependencies": { + "typescript": "5.3.3" + } + }, + "node_modules/@stellar/js-xdr": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@stellar/js-xdr/-/js-xdr-3.1.2.tgz", + "integrity": "sha512-VVolPL5goVEIsvuGqDc5uiKxV03lzfWdvYg1KikvwheDmTBO68CKDji3bAZ/kppZrx5iTA8z3Ld5yuytcvhvOQ==" + }, + "node_modules/@stellar/stellar-base": { + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/@stellar/stellar-base/-/stellar-base-12.1.0.tgz", + "integrity": "sha512-pWwn+XWP5NotmIteZNuJzHeNn9DYSqH3lsYbtFUoSYy1QegzZdi9D8dK6fJ2fpBAnf/rcDjHgHOw3gtHaQFVbg==", + "dependencies": { + "@stellar/js-xdr": "^3.1.2", + "base32.js": "^0.1.0", + "bignumber.js": "^9.1.2", + "buffer": "^6.0.3", + "sha.js": "^2.3.6", + "tweetnacl": "^1.0.3" + }, + "optionalDependencies": { + "sodium-native": "^4.1.1" + } + }, + "node_modules/@stellar/stellar-sdk": { + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/@stellar/stellar-sdk/-/stellar-sdk-12.1.0.tgz", + "integrity": "sha512-Va0hu9SaPezmMbO5eMwL5D15Wrx1AGWRtxayUDRWV2Fr3ynY58mvCZS1vsgNQ4kE8MZe3nBVKv6T9Kzqwgx1PQ==", + "dependencies": { + "@stellar/stellar-base": "^12.0.1", + "axios": "^1.7.2", + "bignumber.js": "^9.1.2", + "eventsource": "^2.0.2", + "randombytes": "^2.1.0", + "toml": "^3.0.0", + "urijs": "^1.19.1" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "node_modules/axios": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.2.tgz", + "integrity": "sha512-2A8QhOMrbomlDuiLeK9XibIBzuHeRcqqNOHp0Cyp5EoJ1IFDh+XZH3A6BkXtv0K4gFGCI0Y4BM7B1wOEi0Rmgw==", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/base32.js": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/base32.js/-/base32.js-0.1.0.tgz", + "integrity": "sha512-n3TkB02ixgBOhTvANakDb4xaMXnYUVkNoRFJjQflcqMQhyEKxEHdj3E6N8t8sUQ0mjH/3/JxzlXuz3ul/J90pQ==", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/bignumber.js": { + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.1.2.tgz", + "integrity": "sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug==", + "engines": { + "node": "*" + } + }, + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/eventsource": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-2.0.2.tgz", + "integrity": "sha512-IzUmBGPR3+oUG9dUeXynyNmf91/3zUSJg1lCktzKw47OXuhco54U3r9B7O4XX+Rb1Itm9OZ2b0RkTs10bICOxA==", + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/follow-redirects": { + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/node-gyp-build": { + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.1.tgz", + "integrity": "sha512-OSs33Z9yWr148JZcbZd5WiAXhh/n9z8TxQcdMhIOlpN9AhWpLfvVFO73+m77bBABQMaY9XSvIa+qk0jlI7Gcaw==", + "optional": true, + "bin": { + "node-gyp-build": "bin.js", + "node-gyp-build-optional": "optional.js", + "node-gyp-build-test": "build-test.js" + } + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "dependencies": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + }, + "bin": { + "sha.js": "bin.js" + } + }, + "node_modules/sodium-native": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/sodium-native/-/sodium-native-4.1.1.tgz", + "integrity": "sha512-LXkAfRd4FHtkQS4X6g+nRcVaN7mWVNepV06phIsC6+IZFvGh1voW5TNQiQp2twVaMf05gZqQjuS+uWLM6gHhNQ==", + "hasInstallScript": true, + "optional": true, + "dependencies": { + "node-gyp-build": "^4.8.0" + } + }, + "node_modules/toml": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/toml/-/toml-3.0.0.tgz", + "integrity": "sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w==" + }, + "node_modules/tweetnacl": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", + "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==" + }, + "node_modules/typescript": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", + "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/urijs": { + "version": "1.19.11", + "resolved": "https://registry.npmjs.org/urijs/-/urijs-1.19.11.tgz", + "integrity": "sha512-HXgFDgDommxn5/bIv0cnQZsPhHDA90NPHD6+c/v21U5+Sx5hoP8+dP9IZXBU1gIfvdRfhG8cel9QNPeionfcCQ==" + } + } +} diff --git a/packages/voting_contract/package.json b/packages/voting_contract/package.json new file mode 100644 index 0000000..47d5e65 --- /dev/null +++ b/packages/voting_contract/package.json @@ -0,0 +1,17 @@ +{ + "version": "0.0.0", + "name": "voting_contract", + "type": "module", + "exports": "./dist/index.js", + "typings": "dist/index.d.ts", + "scripts": { + "build": "tsc" + }, + "dependencies": { + "buffer": "6.0.3", + "@stellar/stellar-sdk": "12.1.0" + }, + "devDependencies": { + "typescript": "5.3.3" + } +} diff --git a/packages/voting_contract/src/index.ts b/packages/voting_contract/src/index.ts new file mode 100644 index 0000000..d9436ab --- /dev/null +++ b/packages/voting_contract/src/index.ts @@ -0,0 +1,170 @@ +import { Buffer } from 'buffer' +import { Address } from '@stellar/stellar-sdk' +import { + AssembledTransaction, + Client as ContractClient, + ClientOptions as ContractClientOptions, + Result, + Spec as ContractSpec, +} from '@stellar/stellar-sdk/contract' +import type { + u32, + i32, + u64, + i64, + u128, + i128, + u256, + i256, + Option, + Typepoint, + Duration, +} from '@stellar/stellar-sdk/contract' +export * from '@stellar/stellar-sdk' +export * as contract from '@stellar/stellar-sdk/contract' +export * as rpc from '@stellar/stellar-sdk/rpc' + +if (typeof window !== 'undefined') { + //@ts-ignore Buffer exists + window.Buffer = window.Buffer || Buffer +} + +export const networks = { + testnet: { + networkPassphrase: 'Test SDF Network ; September 2015', + contractId: 'CA6Z3UEZ6EH6VHKO2EEVDGOZI7CT4SATQP7HNTPWODL5OJSDRULXRJCG', + }, +} as const + +export const Errors = {} + +export interface Client { + /** + * Construct and simulate a create_vote transaction. Returns an `AssembledTransaction` object which will have a `result` field containing the result of the simulation. If this transaction changes contract state, you will need to call `signAndSend()` on the returned object. + */ + create_vote: ( + { + vote_id, + vote_options, + title, + description, + start_date, + end_date, + }: { + vote_id: string + vote_options: Array + title: string + description: string + start_date: string + end_date: string + }, + options?: { + /** + * The fee to pay for the transaction. Default: BASE_FEE + */ + fee?: number + + /** + * The maximum amount of time to wait for the transaction to complete. Default: DEFAULT_TIMEOUT + */ + timeoutInSeconds?: number + + /** + * Whether to automatically simulate the transaction when constructing the AssembledTransaction. Default: true + */ + simulate?: boolean + }, + ) => Promise> + + /** + * Construct and simulate a get_vote transaction. Returns an `AssembledTransaction` object which will have a `result` field containing the result of the simulation. If this transaction changes contract state, you will need to call `signAndSend()` on the returned object. + */ + get_vote: ( + { vote_id }: { vote_id: string }, + options?: { + /** + * The fee to pay for the transaction. Default: BASE_FEE + */ + fee?: number + + /** + * The maximum amount of time to wait for the transaction to complete. Default: DEFAULT_TIMEOUT + */ + timeoutInSeconds?: number + + /** + * Whether to automatically simulate the transaction when constructing the AssembledTransaction. Default: true + */ + simulate?: boolean + }, + ) => Promise>> + + /** + * Construct and simulate a cast transaction. Returns an `AssembledTransaction` object which will have a `result` field containing the result of the simulation. If this transaction changes contract state, you will need to call `signAndSend()` on the returned object. + */ + cast: ( + { + vote_id, + option, + voter, + }: { vote_id: string; option: string; voter: string }, + options?: { + /** + * The fee to pay for the transaction. Default: BASE_FEE + */ + fee?: number + + /** + * The maximum amount of time to wait for the transaction to complete. Default: DEFAULT_TIMEOUT + */ + timeoutInSeconds?: number + + /** + * Whether to automatically simulate the transaction when constructing the AssembledTransaction. Default: true + */ + simulate?: boolean + }, + ) => Promise> + + /** + * Construct and simulate a get_vote_result transaction. Returns an `AssembledTransaction` object which will have a `result` field containing the result of the simulation. If this transaction changes contract state, you will need to call `signAndSend()` on the returned object. + */ + get_vote_result: ( + { vote_id }: { vote_id: string }, + options?: { + /** + * The fee to pay for the transaction. Default: BASE_FEE + */ + fee?: number + + /** + * The maximum amount of time to wait for the transaction to complete. Default: DEFAULT_TIMEOUT + */ + timeoutInSeconds?: number + + /** + * Whether to automatically simulate the transaction when constructing the AssembledTransaction. Default: true + */ + simulate?: boolean + }, + ) => Promise>> +} +export class Client extends ContractClient { + constructor(public readonly options: ContractClientOptions) { + super( + new ContractSpec([ + 'AAAAAAAAAAAAAAALY3JlYXRlX3ZvdGUAAAAABgAAAAAAAAAHdm90ZV9pZAAAAAARAAAAAAAAAAx2b3RlX29wdGlvbnMAAAPqAAAAEQAAAAAAAAAFdGl0bGUAAAAAAAAQAAAAAAAAAAtkZXNjcmlwdGlvbgAAAAAQAAAAAAAAAApzdGFydF9kYXRlAAAAAAAQAAAAAAAAAAhlbmRfZGF0ZQAAABAAAAAA', + 'AAAAAAAAAAAAAAAIZ2V0X3ZvdGUAAAABAAAAAAAAAAd2b3RlX2lkAAAAABEAAAABAAAD6gAAABA=', + 'AAAAAAAAAAAAAAAEY2FzdAAAAAMAAAAAAAAAB3ZvdGVfaWQAAAAAEQAAAAAAAAAGb3B0aW9uAAAAAAARAAAAAAAAAAV2b3RlcgAAAAAAABMAAAAA', + 'AAAAAAAAAAAAAAAPZ2V0X3ZvdGVfcmVzdWx0AAAAAAEAAAAAAAAAB3ZvdGVfaWQAAAAAEQAAAAEAAAPsAAAAEQAAAAQ=', + ]), + options, + ) + } + public readonly fromJSON = { + create_vote: this.txFromJSON, + get_vote: this.txFromJSON>, + cast: this.txFromJSON, + get_vote_result: this.txFromJSON>, + } +} diff --git a/packages/voting_contract/tsconfig.json b/packages/voting_contract/tsconfig.json new file mode 100644 index 0000000..4d120dd --- /dev/null +++ b/packages/voting_contract/tsconfig.json @@ -0,0 +1,96 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig to read more about this file */ + /* Projects */ + // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ + // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ + // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ + // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ + // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ + // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ + /* Language and Environment */ + "target": "ESNext" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */, + // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ + // "jsx": "preserve", /* Specify what JSX code is generated. */ + // "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ + // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ + // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ + // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ + // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ + // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ + // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ + // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ + // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ + /* Modules */ + "module": "NodeNext" /* Specify what module code is generated. */, + // "rootDir": "./", /* Specify the root folder within your source files. */ + "moduleResolution": "nodenext" /* Specify how TypeScript looks up a file from a given module specifier. */, + // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ + // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ + // "types": [], /* Specify type package names to be included without being referenced in a source file. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ + // "resolveJsonModule": true, /* Enable importing .json files. */ + // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ + /* JavaScript Support */ + // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ + // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ + // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ + /* Emit */ + "declaration": true /* Generate .d.ts files from TypeScript and JavaScript files in your project. */, + // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ + // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ + // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ + "outDir": "./dist" /* Specify an output folder for all emitted files. */, + // "removeComments": true, /* Disable emitting comments. */ + // "noEmit": true, /* Disable emitting files from a compilation. */ + // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ + // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ + // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ + // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ + // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ + // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ + // "newLine": "crlf", /* Set the newline character for emitting files. */ + // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ + // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ + // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ + // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ + // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ + /* Interop Constraints */ + // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ + // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ + // "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */ + // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ + // "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */ + /* Type Checking */ + // "strict": true, /* Enable all strict type-checking options. */ + // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ + "strictNullChecks": true /* When type checking, take into account 'null' and 'undefined'. */, + // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ + // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ + // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ + // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ + // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ + // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ + // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ + // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ + // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ + // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ + // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ + // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ + // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ + // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ + // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ + // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ + /* Completeness */ + // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ + "skipLibCheck": true /* Skip type checking all .d.ts files. */ + }, + "include": ["src/*"] +}