├── .editorconfig ├── .eslintrc.json ├── .gitignore ├── .prettierignore ├── .prettierrc ├── .vscode ├── extensions.json └── settings.json ├── README.md ├── apps ├── .gitkeep ├── material-wallet-adapter │ ├── .browserslistrc │ ├── .eslintrc.json │ ├── jest.config.ts │ ├── project.json │ ├── src │ │ ├── app │ │ │ ├── app.component.ts │ │ │ ├── app.module.ts │ │ │ ├── home.component.ts │ │ │ └── operators │ │ │ │ ├── index.ts │ │ │ │ └── not-null.ts │ │ ├── assets │ │ │ └── .gitkeep │ │ ├── environments │ │ │ ├── environment.prod.ts │ │ │ └── environment.ts │ │ ├── favicon.ico │ │ ├── index.html │ │ ├── main.ts │ │ ├── polyfills.ts │ │ ├── styles.scss │ │ └── test-setup.ts │ ├── tailwind.config.js │ ├── tsconfig.app.json │ ├── tsconfig.editor.json │ ├── tsconfig.json │ ├── tsconfig.spec.json │ └── webpack.config.js └── raw-wallet-adapter │ ├── .browserslistrc │ ├── .eslintrc.json │ ├── jest.config.ts │ ├── project.json │ ├── src │ ├── app │ │ ├── app.component.ts │ │ ├── app.module.ts │ │ ├── home.component.ts │ │ └── operators │ │ │ ├── index.ts │ │ │ └── not-null.ts │ ├── assets │ │ └── .gitkeep │ ├── environments │ │ ├── environment.prod.ts │ │ └── environment.ts │ ├── favicon.ico │ ├── index.html │ ├── main.ts │ ├── polyfills.ts │ ├── styles.scss │ └── test-setup.ts │ ├── tsconfig.app.json │ ├── tsconfig.editor.json │ ├── tsconfig.json │ ├── tsconfig.spec.json │ └── webpack.config.js ├── jest.config.js ├── jest.preset.js ├── libs └── .gitkeep ├── nx.json ├── package-lock.json ├── package.json ├── tools ├── generators │ └── .gitkeep └── tsconfig.tools.json ├── tsconfig.base.json └── workspace.json /.editorconfig: -------------------------------------------------------------------------------- 1 | # Editor configuration, see http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 2 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.md] 12 | max_line_length = off 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "root": true, 3 | "ignorePatterns": ["**/*"], 4 | "plugins": ["@nrwl/nx"], 5 | "overrides": [ 6 | { 7 | "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], 8 | "rules": { 9 | "@nrwl/nx/enforce-module-boundaries": [ 10 | "error", 11 | { 12 | "enforceBuildableLibDependency": true, 13 | "allow": [], 14 | "depConstraints": [ 15 | { 16 | "sourceTag": "*", 17 | "onlyDependOnLibsWithTags": ["*"] 18 | } 19 | ] 20 | } 21 | ] 22 | } 23 | }, 24 | { 25 | "files": ["*.ts", "*.tsx"], 26 | "extends": ["plugin:@nrwl/nx/typescript"], 27 | "rules": {} 28 | }, 29 | { 30 | "files": ["*.js", "*.jsx"], 31 | "extends": ["plugin:@nrwl/nx/javascript"], 32 | "rules": {} 33 | } 34 | ] 35 | } 36 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # compiled output 4 | /dist 5 | /tmp 6 | /out-tsc 7 | 8 | # dependencies 9 | /node_modules 10 | 11 | # IDEs and editors 12 | /.idea 13 | .project 14 | .classpath 15 | .c9/ 16 | *.launch 17 | .settings/ 18 | *.sublime-workspace 19 | 20 | # IDE - VSCode 21 | .vscode/* 22 | !.vscode/settings.json 23 | !.vscode/tasks.json 24 | !.vscode/launch.json 25 | !.vscode/extensions.json 26 | 27 | # misc 28 | /.sass-cache 29 | /connect.lock 30 | /coverage 31 | /libpeerconnection.log 32 | npm-debug.log 33 | yarn-error.log 34 | testem.log 35 | /typings 36 | 37 | # System Files 38 | .DS_Store 39 | Thumbs.db 40 | 41 | # Angular 42 | .angular 43 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | # Add files here to ignore them from prettier formatting 2 | 3 | /dist 4 | /coverage 5 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true 3 | } 4 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "nrwl.angular-console", 4 | "esbenp.prettier-vscode", 5 | "firsttris.vscode-jest-runner", 6 | "dbaeumer.vscode-eslint" 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "workbench.colorCustomizations": { 3 | "activityBar.activeBackground": "#911b77", 4 | "activityBar.activeBorder": "#161b05", 5 | "activityBar.background": "#911b77", 6 | "activityBar.foreground": "#e7e7e7", 7 | "activityBar.inactiveForeground": "#e7e7e799", 8 | "activityBarBadge.background": "#161b05", 9 | "activityBarBadge.foreground": "#e7e7e7", 10 | "sash.hoverBorder": "#911b77", 11 | "statusBar.background": "#661354", 12 | "statusBar.foreground": "#e7e7e7", 13 | "statusBarItem.hoverBackground": "#911b77", 14 | "statusBarItem.remoteBackground": "#661354", 15 | "statusBarItem.remoteForeground": "#e7e7e7", 16 | "titleBar.activeBackground": "#661354", 17 | "titleBar.activeForeground": "#e7e7e7", 18 | "titleBar.inactiveBackground": "#66135499", 19 | "titleBar.inactiveForeground": "#e7e7e799" 20 | }, 21 | "peacock.color": "#661354", 22 | "editor.defaultFormatter": "esbenp.prettier-vscode", 23 | "editor.formatOnSave": true, 24 | "editor.codeActionsOnSave": { 25 | "source.organizeImports": true 26 | }, 27 | } 28 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Angular Wallet Adapter Sample 2 | 3 | This project shows how to use `@heavy-duty/wallet-adapter` package in an Angular application inside a Nx workspace. 4 | 5 | ## Development server 6 | 7 | Install all required dependencies using `npm install` from the root path of the project. Run `nx serve web-client` for a dev server. Navigate to http://localhost:4200/. The app will automatically reload if you change any of the source files. 8 | -------------------------------------------------------------------------------- /apps/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danmt/wallet-adapter-angular-sample/3dff199a052ce88077a0cc97d0c2467a24c14425/apps/.gitkeep -------------------------------------------------------------------------------- /apps/material-wallet-adapter/.browserslistrc: -------------------------------------------------------------------------------- 1 | # This file is used by the build system to adjust CSS and JS output to support the specified browsers below. 2 | # For additional information regarding the format and rule options, please see: 3 | # https://github.com/browserslist/browserslist#queries 4 | 5 | # For the full list of supported browsers by the Angular framework, please see: 6 | # https://angular.io/guide/browser-support 7 | 8 | # You can see what browsers were selected by your queries by running: 9 | # npx browserslist 10 | 11 | last 1 Chrome version 12 | last 1 Firefox version 13 | last 2 Edge major versions 14 | last 2 Safari major versions 15 | last 2 iOS major versions 16 | Firefox ESR 17 | -------------------------------------------------------------------------------- /apps/material-wallet-adapter/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["../../.eslintrc.json"], 3 | "ignorePatterns": ["!**/*"], 4 | "overrides": [ 5 | { 6 | "files": ["*.ts"], 7 | "extends": [ 8 | "plugin:@nrwl/nx/angular", 9 | "plugin:@angular-eslint/template/process-inline-templates" 10 | ], 11 | "rules": { 12 | "@angular-eslint/directive-selector": [ 13 | "error", 14 | { 15 | "type": "attribute", 16 | "prefix": "wa", 17 | "style": "camelCase" 18 | } 19 | ], 20 | "@angular-eslint/component-selector": [ 21 | "error", 22 | { 23 | "type": "element", 24 | "prefix": "wa", 25 | "style": "kebab-case" 26 | } 27 | ] 28 | } 29 | }, 30 | { 31 | "files": ["*.html"], 32 | "extends": ["plugin:@nrwl/nx/angular-template"], 33 | "rules": {} 34 | } 35 | ] 36 | } 37 | -------------------------------------------------------------------------------- /apps/material-wallet-adapter/jest.config.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | export default { 3 | displayName: 'material-wallet-adapter', 4 | preset: '../../jest.preset.js', 5 | setupFilesAfterEnv: ['/src/test-setup.ts'], 6 | globals: { 7 | 'ts-jest': { 8 | tsconfig: '/tsconfig.spec.json', 9 | stringifyContentPathRegex: '\\.(html|svg)$', 10 | }, 11 | }, 12 | coverageDirectory: '../../coverage/apps/material-wallet-adapter', 13 | transform: { 14 | '^.+\\.(ts|mjs|js|html)$': 'jest-preset-angular', 15 | }, 16 | transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'], 17 | snapshotSerializers: [ 18 | 'jest-preset-angular/build/serializers/no-ng-attributes', 19 | 'jest-preset-angular/build/serializers/ng-snapshot', 20 | 'jest-preset-angular/build/serializers/html-comment', 21 | ], 22 | }; 23 | -------------------------------------------------------------------------------- /apps/material-wallet-adapter/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "projectType": "application", 3 | "sourceRoot": "apps/material-wallet-adapter/src", 4 | "prefix": "wa", 5 | "targets": { 6 | "build": { 7 | "executor": "@nrwl/angular:webpack-browser", 8 | "outputs": ["{options.outputPath}"], 9 | "options": { 10 | "outputPath": "dist/apps/material-wallet-adapter", 11 | "index": "apps/material-wallet-adapter/src/index.html", 12 | "main": "apps/material-wallet-adapter/src/main.ts", 13 | "polyfills": "apps/material-wallet-adapter/src/polyfills.ts", 14 | "tsConfig": "apps/material-wallet-adapter/tsconfig.app.json", 15 | "inlineStyleLanguage": "scss", 16 | "assets": [ 17 | "apps/material-wallet-adapter/src/favicon.ico", 18 | "apps/material-wallet-adapter/src/assets" 19 | ], 20 | "styles": [ 21 | "apps/material-wallet-adapter/src/styles.scss", 22 | "node_modules/@angular/material/prebuilt-themes/purple-green.css", 23 | "node_modules/@heavy-duty/wallet-adapter-material/src/style.css" 24 | ], 25 | "scripts": [], 26 | "customWebpackConfig": { 27 | "path": "apps/material-wallet-adapter/webpack.config.js" 28 | } 29 | }, 30 | "configurations": { 31 | "production": { 32 | "budgets": [ 33 | { 34 | "type": "initial", 35 | "maximumWarning": "500kb", 36 | "maximumError": "1mb" 37 | }, 38 | { 39 | "type": "anyComponentStyle", 40 | "maximumWarning": "2kb", 41 | "maximumError": "4kb" 42 | } 43 | ], 44 | "fileReplacements": [ 45 | { 46 | "replace": "apps/material-wallet-adapter/src/environments/environment.ts", 47 | "with": "apps/material-wallet-adapter/src/environments/environment.prod.ts" 48 | } 49 | ], 50 | "outputHashing": "all" 51 | }, 52 | "development": { 53 | "buildOptimizer": false, 54 | "optimization": false, 55 | "vendorChunk": true, 56 | "extractLicenses": false, 57 | "sourceMap": true, 58 | "namedChunks": true 59 | } 60 | }, 61 | "defaultConfiguration": "production" 62 | }, 63 | "serve": { 64 | "executor": "@nrwl/angular:webpack-server", 65 | "configurations": { 66 | "production": { 67 | "browserTarget": "material-wallet-adapter:build:production" 68 | }, 69 | "development": { 70 | "browserTarget": "material-wallet-adapter:build:development" 71 | } 72 | }, 73 | "defaultConfiguration": "development" 74 | }, 75 | "extract-i18n": { 76 | "executor": "@angular-devkit/build-angular:extract-i18n", 77 | "options": { 78 | "browserTarget": "material-wallet-adapter:build" 79 | } 80 | }, 81 | "lint": { 82 | "executor": "@nrwl/linter:eslint", 83 | "options": { 84 | "lintFilePatterns": [ 85 | "apps/material-wallet-adapter/**/*.ts", 86 | "apps/material-wallet-adapter/**/*.html" 87 | ] 88 | } 89 | }, 90 | "test": { 91 | "executor": "@nrwl/jest:jest", 92 | "outputs": ["coverage/apps/material-wallet-adapter"], 93 | "options": { 94 | "jestConfig": "apps/material-wallet-adapter/jest.config.ts", 95 | "passWithNoTests": true 96 | } 97 | } 98 | }, 99 | "tags": [] 100 | } 101 | -------------------------------------------------------------------------------- /apps/material-wallet-adapter/src/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { WalletAdapterNetwork } from '@solana/wallet-adapter-base'; 3 | import { 4 | LedgerWalletAdapter, 5 | PhantomWalletAdapter, 6 | SlopeWalletAdapter, 7 | SolflareWalletAdapter, 8 | SolletWalletAdapter, 9 | TorusWalletAdapter, 10 | } from '@solana/wallet-adapter-wallets'; 11 | import { ConnectionStore, WalletStore } from '@heavy-duty/wallet-adapter'; 12 | 13 | @Component({ 14 | selector: 'wa-root', 15 | template: ` `, 16 | }) 17 | export class AppComponent implements OnInit { 18 | constructor( 19 | private _connectionStore: ConnectionStore, 20 | private _walletStore: WalletStore 21 | ) {} 22 | 23 | ngOnInit() { 24 | this._connectionStore.setEndpoint('http://api.devnet.solana.com'); 25 | this._walletStore.setAdapters([ 26 | new PhantomWalletAdapter(), 27 | new SlopeWalletAdapter(), 28 | new SolflareWalletAdapter(), 29 | new TorusWalletAdapter(), 30 | new LedgerWalletAdapter(), 31 | new SolletWalletAdapter({ network: WalletAdapterNetwork.Devnet }), 32 | ]); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /apps/material-wallet-adapter/src/app/app.module.ts: -------------------------------------------------------------------------------- 1 | import { ClipboardModule } from '@angular/cdk/clipboard'; 2 | import { DialogModule } from '@angular/cdk/dialog'; 3 | import { NgModule } from '@angular/core'; 4 | import { ReactiveFormsModule } from '@angular/forms'; 5 | import { MatButtonModule } from '@angular/material/button'; 6 | import { MatCardModule } from '@angular/material/card'; 7 | import { MatFormFieldModule } from '@angular/material/form-field'; 8 | import { MatIconModule } from '@angular/material/icon'; 9 | import { MatInputModule } from '@angular/material/input'; 10 | import { BrowserModule } from '@angular/platform-browser'; 11 | import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; 12 | import { HdWalletAdapterModule } from '@heavy-duty/wallet-adapter'; 13 | import { HdWalletAdapterMaterialModule } from '@heavy-duty/wallet-adapter-material'; 14 | import { AppComponent } from './app.component'; 15 | import { HomeComponent } from './home.component'; 16 | 17 | @NgModule({ 18 | declarations: [AppComponent, HomeComponent], 19 | imports: [ 20 | BrowserModule, 21 | BrowserAnimationsModule, 22 | ReactiveFormsModule, 23 | ClipboardModule, 24 | DialogModule, 25 | MatButtonModule, 26 | MatCardModule, 27 | MatFormFieldModule, 28 | MatIconModule, 29 | MatInputModule, 30 | HdWalletAdapterModule.forRoot({ autoConnect: true }), 31 | HdWalletAdapterMaterialModule, 32 | ], 33 | bootstrap: [AppComponent], 34 | }) 35 | export class AppModule {} 36 | -------------------------------------------------------------------------------- /apps/material-wallet-adapter/src/app/home.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { FormBuilder, FormControl } from '@angular/forms'; 3 | import { ConnectionStore, WalletStore } from '@heavy-duty/wallet-adapter'; 4 | import { WalletName, WalletReadyState } from '@solana/wallet-adapter-base'; 5 | import { PublicKey, SystemProgram, Transaction } from '@solana/web3.js'; 6 | import { encode } from 'bs58'; 7 | import { defer, from, throwError } from 'rxjs'; 8 | import { concatMap, first, map } from 'rxjs/operators'; 9 | import { isNotNull } from './operators'; 10 | 11 | @Component({ 12 | selector: 'wa-home', 13 | template: ` 14 |
15 |

@heavy-duty/wallet-adapter example

16 |
17 | 18 |
19 | 20 |

21 | Wallet details ({{ walletName$ | async }} - 22 | (READY)) 23 |

24 | 25 |
26 | 27 |
28 | 29 |

33 | 34 | {{ publicKey.toBase58() }} 35 | 36 | 37 | 40 |

41 |
42 | 43 | 44 |

Transaction

45 |
46 | 47 | Recipient 48 | 54 | 55 | 56 | 57 | Lamports 58 | 64 | 65 | 66 |
67 | 75 | 83 | 91 | 99 |
100 |
101 |
102 | 103 | 104 |

Message

105 |
106 | 114 |
115 |
116 |
117 | `, 118 | }) 119 | export class HomeComponent { 120 | readonly connection$ = this._connectionStore.connection$; 121 | readonly wallets$ = this._walletStore.wallets$; 122 | readonly wallet$ = this._walletStore.wallet$; 123 | readonly walletName$ = this.wallet$.pipe( 124 | map((wallet) => wallet?.adapter.name || null) 125 | ); 126 | readonly ready$ = this.wallet$.pipe( 127 | map( 128 | (wallet) => 129 | wallet && 130 | (wallet.adapter.readyState === WalletReadyState.Installed || 131 | wallet.adapter.readyState === WalletReadyState.Loadable) 132 | ) 133 | ); 134 | readonly connected$ = this._walletStore.connected$; 135 | readonly publicKey$ = this._walletStore.publicKey$; 136 | lamports = 0; 137 | recipient = ''; 138 | readonly form = this._formBuilder.group<{ 139 | recipient: FormControl; 140 | lamports: FormControl; 141 | }>({ 142 | recipient: this._formBuilder.control(null), 143 | lamports: this._formBuilder.control(null), 144 | }); 145 | 146 | constructor( 147 | private readonly _formBuilder: FormBuilder, 148 | private readonly _connectionStore: ConnectionStore, 149 | private readonly _walletStore: WalletStore 150 | ) {} 151 | 152 | onConnect() { 153 | this._walletStore.connect().subscribe(); 154 | } 155 | 156 | onDisconnect() { 157 | this._walletStore.disconnect().subscribe(); 158 | } 159 | 160 | onSelectWallet(walletName: WalletName) { 161 | this._walletStore.selectWallet(walletName); 162 | } 163 | 164 | onSendTransaction(fromPubkey: PublicKey) { 165 | const { lamports, recipient } = this.form.value; 166 | 167 | if (!lamports || !recipient) { 168 | throw new Error('Invalid data'); 169 | } 170 | 171 | this.connection$ 172 | .pipe( 173 | first(), 174 | isNotNull, 175 | concatMap((connection) => 176 | from(defer(() => connection.getLatestBlockhash())).pipe( 177 | concatMap(({ blockhash, lastValidBlockHeight }) => 178 | this._walletStore.sendTransaction( 179 | new Transaction({ 180 | blockhash, 181 | feePayer: fromPubkey, 182 | lastValidBlockHeight, 183 | }).add( 184 | SystemProgram.transfer({ 185 | fromPubkey, 186 | toPubkey: new PublicKey(recipient), 187 | lamports, 188 | }) 189 | ), 190 | connection 191 | ) 192 | ) 193 | ) 194 | ) 195 | ) 196 | .subscribe({ 197 | next: (signature) => console.log(`Transaction sent (${signature})`), 198 | error: (error) => console.error(error), 199 | }); 200 | } 201 | 202 | onSignTransaction(fromPubkey: PublicKey) { 203 | const { lamports, recipient } = this.form.value; 204 | 205 | if (!lamports || !recipient) { 206 | throw new Error('Invalid data'); 207 | } 208 | 209 | this.connection$ 210 | .pipe( 211 | first(), 212 | isNotNull, 213 | concatMap((connection) => 214 | from(defer(() => connection.getLatestBlockhash())).pipe( 215 | map(({ blockhash, lastValidBlockHeight }) => 216 | new Transaction({ 217 | blockhash, 218 | feePayer: fromPubkey, 219 | lastValidBlockHeight, 220 | }).add( 221 | SystemProgram.transfer({ 222 | fromPubkey, 223 | toPubkey: new PublicKey(recipient), 224 | lamports, 225 | }) 226 | ) 227 | ) 228 | ) 229 | ), 230 | concatMap((transaction) => { 231 | const signTransaction$ = 232 | this._walletStore.signTransaction(transaction); 233 | 234 | if (!signTransaction$) { 235 | return throwError( 236 | () => new Error('Sign transaction method is not defined') 237 | ); 238 | } 239 | 240 | return signTransaction$; 241 | }) 242 | ) 243 | .subscribe({ 244 | next: (transaction) => console.log('Transaction signed', transaction), 245 | error: (error) => console.error(error), 246 | }); 247 | } 248 | 249 | onSignAllTransactions(fromPubkey: PublicKey) { 250 | const { lamports, recipient } = this.form.value; 251 | 252 | if (!lamports || !recipient) { 253 | throw new Error('Invalid data'); 254 | } 255 | 256 | this.connection$ 257 | .pipe( 258 | first(), 259 | isNotNull, 260 | concatMap((connection) => 261 | from(defer(() => connection.getLatestBlockhash())).pipe( 262 | map(({ blockhash, lastValidBlockHeight }) => 263 | new Array(3).fill(0).map(() => 264 | new Transaction({ 265 | blockhash, 266 | feePayer: fromPubkey, 267 | lastValidBlockHeight, 268 | }).add( 269 | SystemProgram.transfer({ 270 | fromPubkey, 271 | toPubkey: new PublicKey(recipient), 272 | lamports, 273 | }) 274 | ) 275 | ) 276 | ) 277 | ) 278 | ), 279 | concatMap((transactions) => { 280 | const signAllTransaction$ = 281 | this._walletStore.signAllTransactions(transactions); 282 | 283 | if (!signAllTransaction$) { 284 | return throwError( 285 | () => new Error('Sign all transactions method is not defined') 286 | ); 287 | } 288 | 289 | return signAllTransaction$; 290 | }) 291 | ) 292 | .subscribe({ 293 | next: (transactions) => 294 | console.log('Transactions signed', transactions), 295 | error: (error) => console.error(error), 296 | }); 297 | } 298 | 299 | onSignMessage() { 300 | const signMessage$ = this._walletStore.signMessage( 301 | new TextEncoder().encode('Hello world!') 302 | ); 303 | 304 | if (!signMessage$) { 305 | return console.error(new Error('Sign message method is not defined')); 306 | } 307 | 308 | signMessage$.pipe(first()).subscribe((signature) => { 309 | console.log(`Message signature: ${{ encode }.encode(signature)}`); 310 | }); 311 | } 312 | } 313 | -------------------------------------------------------------------------------- /apps/material-wallet-adapter/src/app/operators/index.ts: -------------------------------------------------------------------------------- 1 | export * from './not-null'; 2 | -------------------------------------------------------------------------------- /apps/material-wallet-adapter/src/app/operators/not-null.ts: -------------------------------------------------------------------------------- 1 | import { Observable } from 'rxjs'; 2 | import { filter } from 'rxjs/operators'; 3 | 4 | export const isNotNull = (source: Observable) => 5 | source.pipe(filter((item: T | null): item is T => item !== null)); 6 | -------------------------------------------------------------------------------- /apps/material-wallet-adapter/src/assets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danmt/wallet-adapter-angular-sample/3dff199a052ce88077a0cc97d0c2467a24c14425/apps/material-wallet-adapter/src/assets/.gitkeep -------------------------------------------------------------------------------- /apps/material-wallet-adapter/src/environments/environment.prod.ts: -------------------------------------------------------------------------------- 1 | export const environment = { 2 | production: true, 3 | }; 4 | -------------------------------------------------------------------------------- /apps/material-wallet-adapter/src/environments/environment.ts: -------------------------------------------------------------------------------- 1 | // This file can be replaced during build by using the `fileReplacements` array. 2 | // `ng build` replaces `environment.ts` with `environment.prod.ts`. 3 | // The list of file replacements can be found in `angular.json`. 4 | 5 | export const environment = { 6 | production: false, 7 | }; 8 | 9 | /* 10 | * For easier debugging in development mode, you can import the following file 11 | * to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`. 12 | * 13 | * This import should be commented out in production mode because it will have a negative impact 14 | * on performance if an error is thrown. 15 | */ 16 | // import 'zone.js/plugins/zone-error'; // Included with Angular CLI. 17 | -------------------------------------------------------------------------------- /apps/material-wallet-adapter/src/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danmt/wallet-adapter-angular-sample/3dff199a052ce88077a0cc97d0c2467a24c14425/apps/material-wallet-adapter/src/favicon.ico -------------------------------------------------------------------------------- /apps/material-wallet-adapter/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | MaterialWalletAdapter 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /apps/material-wallet-adapter/src/main.ts: -------------------------------------------------------------------------------- 1 | import { enableProdMode } from '@angular/core'; 2 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 3 | 4 | import { AppModule } from './app/app.module'; 5 | import { environment } from './environments/environment'; 6 | 7 | if (environment.production) { 8 | enableProdMode(); 9 | } 10 | 11 | platformBrowserDynamic() 12 | .bootstrapModule(AppModule) 13 | .catch((err) => console.error(err)); 14 | -------------------------------------------------------------------------------- /apps/material-wallet-adapter/src/polyfills.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This file includes polyfills needed by Angular and is loaded before the app. 3 | * You can add your own extra polyfills to this file. 4 | * 5 | * This file is divided into 2 sections: 6 | * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers. 7 | * 2. Application imports. Files imported after ZoneJS that should be loaded before your main 8 | * file. 9 | * 10 | * The current setup is for so-called "evergreen" browsers; the last versions of browsers that 11 | * automatically update themselves. This includes recent versions of Safari, Chrome (including 12 | * Opera), Edge on the desktop, and iOS and Chrome on mobile. 13 | * 14 | * Learn more in https://angular.io/guide/browser-support 15 | */ 16 | 17 | /*************************************************************************************************** 18 | * BROWSER POLYFILLS 19 | */ 20 | 21 | /** 22 | * By default, zone.js will patch all possible macroTask and DomEvents 23 | * user can disable parts of macroTask/DomEvents patch by setting following flags 24 | * because those flags need to be set before `zone.js` being loaded, and webpack 25 | * will put import in the top of bundle, so user need to create a separate file 26 | * in this directory (for example: zone-flags.ts), and put the following flags 27 | * into that file, and then add the following code before importing zone.js. 28 | * import './zone-flags'; 29 | * 30 | * The flags allowed in zone-flags.ts are listed here. 31 | * 32 | * The following flags will work for all browsers. 33 | * 34 | * (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame 35 | * (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick 36 | * (window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames 37 | * 38 | * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js 39 | * with the following flag, it will bypass `zone.js` patch for IE/Edge 40 | * 41 | * (window as any).__Zone_enable_cross_context_check = true; 42 | * 43 | */ 44 | 45 | /*************************************************************************************************** 46 | * Zone JS is required by default for Angular itself. 47 | */ 48 | import 'zone.js'; // Included with Angular CLI. 49 | 50 | /*************************************************************************************************** 51 | * APPLICATION IMPORTS 52 | */ 53 | import { Buffer } from 'buffer'; 54 | (window as any).global = window; 55 | global.Buffer = global.Buffer || Buffer; 56 | (window as any).process = { 57 | version: '', 58 | }; 59 | -------------------------------------------------------------------------------- /apps/material-wallet-adapter/src/styles.scss: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/icon?family=Material+Icons'); 2 | @import url('https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500&display=swap'); 3 | @tailwind base; 4 | @tailwind components; 5 | @tailwind utilities; 6 | 7 | html, 8 | body { 9 | height: 100%; 10 | } 11 | 12 | body { 13 | margin: 0; 14 | padding: 1rem; 15 | } 16 | -------------------------------------------------------------------------------- /apps/material-wallet-adapter/src/test-setup.ts: -------------------------------------------------------------------------------- 1 | import 'jest-preset-angular/setup-jest'; 2 | -------------------------------------------------------------------------------- /apps/material-wallet-adapter/tailwind.config.js: -------------------------------------------------------------------------------- 1 | const { createGlobPatternsForDependencies } = require('@nrwl/angular/tailwind'); 2 | const { join } = require('path'); 3 | 4 | module.exports = { 5 | content: [ 6 | join(__dirname, 'src/**/!(*.stories|*.spec).{ts,html}'), 7 | ...createGlobPatternsForDependencies(__dirname), 8 | ], 9 | theme: { 10 | extend: {}, 11 | }, 12 | plugins: [], 13 | important: true, 14 | }; 15 | -------------------------------------------------------------------------------- /apps/material-wallet-adapter/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "types": [] 6 | }, 7 | "files": ["src/main.ts", "src/polyfills.ts"], 8 | "include": ["src/**/*.d.ts"], 9 | "exclude": ["**/*.test.ts", "**/*.spec.ts"] 10 | } 11 | -------------------------------------------------------------------------------- /apps/material-wallet-adapter/tsconfig.editor.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "include": ["**/*.ts"], 4 | "compilerOptions": { 5 | "types": ["jest", "node"] 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /apps/material-wallet-adapter/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "files": [], 4 | "include": [], 5 | "references": [ 6 | { 7 | "path": "./tsconfig.app.json" 8 | }, 9 | { 10 | "path": "./tsconfig.spec.json" 11 | }, 12 | { 13 | "path": "./tsconfig.editor.json" 14 | } 15 | ], 16 | "compilerOptions": { 17 | "target": "es2020", 18 | "forceConsistentCasingInFileNames": true, 19 | "strict": true, 20 | "noImplicitOverride": true, 21 | "noPropertyAccessFromIndexSignature": true, 22 | "noImplicitReturns": true, 23 | "noFallthroughCasesInSwitch": true 24 | }, 25 | "angularCompilerOptions": { 26 | "enableI18nLegacyMessageIdFormat": false, 27 | "strictInjectionParameters": true, 28 | "strictInputAccessModifiers": true, 29 | "strictTemplates": true 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /apps/material-wallet-adapter/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "module": "commonjs", 6 | "types": ["jest", "node"] 7 | }, 8 | "files": ["src/test-setup.ts"], 9 | "include": ["jest.config.ts", "**/*.test.ts", "**/*.spec.ts", "**/*.d.ts"] 10 | } 11 | -------------------------------------------------------------------------------- /apps/material-wallet-adapter/webpack.config.js: -------------------------------------------------------------------------------- 1 | module.exports = (config) => { 2 | config.resolve.fallback = { 3 | crypto: false, 4 | assert: false, 5 | stream: false 6 | }; 7 | 8 | return config; 9 | }; 10 | -------------------------------------------------------------------------------- /apps/raw-wallet-adapter/.browserslistrc: -------------------------------------------------------------------------------- 1 | # This file is used by the build system to adjust CSS and JS output to support the specified browsers below. 2 | # For additional information regarding the format and rule options, please see: 3 | # https://github.com/browserslist/browserslist#queries 4 | 5 | # For the full list of supported browsers by the Angular framework, please see: 6 | # https://angular.io/guide/browser-support 7 | 8 | # You can see what browsers were selected by your queries by running: 9 | # npx browserslist 10 | 11 | last 1 Chrome version 12 | last 1 Firefox version 13 | last 2 Edge major versions 14 | last 2 Safari major versions 15 | last 2 iOS major versions 16 | Firefox ESR 17 | -------------------------------------------------------------------------------- /apps/raw-wallet-adapter/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["../../.eslintrc.json"], 3 | "ignorePatterns": ["!**/*"], 4 | "overrides": [ 5 | { 6 | "files": ["*.ts"], 7 | "extends": [ 8 | "plugin:@nrwl/nx/angular", 9 | "plugin:@angular-eslint/template/process-inline-templates" 10 | ], 11 | "rules": { 12 | "@angular-eslint/directive-selector": [ 13 | "error", 14 | { 15 | "type": "attribute", 16 | "prefix": "wa", 17 | "style": "camelCase" 18 | } 19 | ], 20 | "@angular-eslint/component-selector": [ 21 | "error", 22 | { 23 | "type": "element", 24 | "prefix": "wa", 25 | "style": "kebab-case" 26 | } 27 | ] 28 | } 29 | }, 30 | { 31 | "files": ["*.html"], 32 | "extends": ["plugin:@nrwl/nx/angular-template"], 33 | "rules": {} 34 | } 35 | ] 36 | } 37 | -------------------------------------------------------------------------------- /apps/raw-wallet-adapter/jest.config.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | export default { 3 | displayName: 'raw-wallet-adapter', 4 | preset: '../../jest.preset.js', 5 | setupFilesAfterEnv: ['/src/test-setup.ts'], 6 | globals: { 7 | 'ts-jest': { 8 | tsconfig: '/tsconfig.spec.json', 9 | stringifyContentPathRegex: '\\.(html|svg)$', 10 | }, 11 | }, 12 | coverageDirectory: '../../coverage/apps/raw-wallet-adapter', 13 | transform: { 14 | '^.+\\.(ts|mjs|js|html)$': 'jest-preset-angular', 15 | }, 16 | transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'], 17 | snapshotSerializers: [ 18 | 'jest-preset-angular/build/serializers/no-ng-attributes', 19 | 'jest-preset-angular/build/serializers/ng-snapshot', 20 | 'jest-preset-angular/build/serializers/html-comment', 21 | ], 22 | }; 23 | -------------------------------------------------------------------------------- /apps/raw-wallet-adapter/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "projectType": "application", 3 | "sourceRoot": "apps/raw-wallet-adapter/src", 4 | "prefix": "wa", 5 | "targets": { 6 | "build": { 7 | "executor": "@nrwl/angular:webpack-browser", 8 | "outputs": ["{options.outputPath}"], 9 | "options": { 10 | "outputPath": "dist/apps/raw-wallet-adapter", 11 | "index": "apps/raw-wallet-adapter/src/index.html", 12 | "main": "apps/raw-wallet-adapter/src/main.ts", 13 | "polyfills": "apps/raw-wallet-adapter/src/polyfills.ts", 14 | "tsConfig": "apps/raw-wallet-adapter/tsconfig.app.json", 15 | "inlineStyleLanguage": "scss", 16 | "assets": [ 17 | "apps/raw-wallet-adapter/src/favicon.ico", 18 | "apps/raw-wallet-adapter/src/assets" 19 | ], 20 | "styles": ["apps/raw-wallet-adapter/src/styles.scss"], 21 | "scripts": [], 22 | "customWebpackConfig": { 23 | "path": "apps/raw-wallet-adapter/webpack.config.js" 24 | } 25 | }, 26 | "configurations": { 27 | "production": { 28 | "budgets": [ 29 | { 30 | "type": "initial", 31 | "maximumWarning": "500kb", 32 | "maximumError": "1mb" 33 | }, 34 | { 35 | "type": "anyComponentStyle", 36 | "maximumWarning": "2kb", 37 | "maximumError": "4kb" 38 | } 39 | ], 40 | "fileReplacements": [ 41 | { 42 | "replace": "apps/raw-wallet-adapter/src/environments/environment.ts", 43 | "with": "apps/raw-wallet-adapter/src/environments/environment.prod.ts" 44 | } 45 | ], 46 | "outputHashing": "all" 47 | }, 48 | "development": { 49 | "buildOptimizer": false, 50 | "optimization": false, 51 | "vendorChunk": true, 52 | "extractLicenses": false, 53 | "sourceMap": true, 54 | "namedChunks": true 55 | } 56 | }, 57 | "defaultConfiguration": "production" 58 | }, 59 | "serve": { 60 | "executor": "@nrwl/angular:webpack-server", 61 | "configurations": { 62 | "production": { 63 | "browserTarget": "raw-wallet-adapter:build:production" 64 | }, 65 | "development": { 66 | "browserTarget": "raw-wallet-adapter:build:development" 67 | } 68 | }, 69 | "defaultConfiguration": "development" 70 | }, 71 | "extract-i18n": { 72 | "executor": "@angular-devkit/build-angular:extract-i18n", 73 | "options": { 74 | "browserTarget": "raw-wallet-adapter:build" 75 | } 76 | }, 77 | "lint": { 78 | "executor": "@nrwl/linter:eslint", 79 | "options": { 80 | "lintFilePatterns": [ 81 | "apps/raw-wallet-adapter/**/*.ts", 82 | "apps/raw-wallet-adapter/**/*.html" 83 | ] 84 | } 85 | }, 86 | "test": { 87 | "executor": "@nrwl/jest:jest", 88 | "outputs": ["coverage/apps/raw-wallet-adapter"], 89 | "options": { 90 | "jestConfig": "apps/raw-wallet-adapter/jest.config.ts", 91 | "passWithNoTests": true 92 | } 93 | } 94 | }, 95 | "tags": [] 96 | } 97 | -------------------------------------------------------------------------------- /apps/raw-wallet-adapter/src/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { WalletAdapterNetwork } from '@solana/wallet-adapter-base'; 3 | import { 4 | LedgerWalletAdapter, 5 | PhantomWalletAdapter, 6 | SlopeWalletAdapter, 7 | SolflareWalletAdapter, 8 | SolletWalletAdapter, 9 | TorusWalletAdapter, 10 | } from '@solana/wallet-adapter-wallets'; 11 | import { ConnectionStore, WalletStore } from '@heavy-duty/wallet-adapter'; 12 | 13 | @Component({ 14 | selector: 'wa-root', 15 | template: ` `, 16 | }) 17 | export class AppComponent implements OnInit { 18 | constructor( 19 | private _connectionStore: ConnectionStore, 20 | private _walletStore: WalletStore 21 | ) {} 22 | 23 | ngOnInit() { 24 | this._connectionStore.setEndpoint('http://api.devnet.solana.com'); 25 | this._walletStore.setAdapters([ 26 | new PhantomWalletAdapter(), 27 | new SlopeWalletAdapter(), 28 | new SolflareWalletAdapter(), 29 | new TorusWalletAdapter(), 30 | new LedgerWalletAdapter(), 31 | new SolletWalletAdapter({ network: WalletAdapterNetwork.Devnet }), 32 | ]); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /apps/raw-wallet-adapter/src/app/app.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { FormsModule } from '@angular/forms'; 3 | import { BrowserModule } from '@angular/platform-browser'; 4 | import { HdWalletAdapterModule } from '@heavy-duty/wallet-adapter'; 5 | import { AppComponent } from './app.component'; 6 | import { HomeComponent } from './home.component'; 7 | 8 | @NgModule({ 9 | declarations: [AppComponent, HomeComponent], 10 | imports: [ 11 | BrowserModule, 12 | FormsModule, 13 | HdWalletAdapterModule.forRoot({ autoConnect: true }), 14 | ], 15 | bootstrap: [AppComponent], 16 | }) 17 | export class AppModule {} 18 | -------------------------------------------------------------------------------- /apps/raw-wallet-adapter/src/app/home.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { WalletName, WalletReadyState } from '@solana/wallet-adapter-base'; 3 | import { PublicKey, SystemProgram, Transaction } from '@solana/web3.js'; 4 | import { encode } from 'bs58'; 5 | import { defer, from, throwError } from 'rxjs'; 6 | import { concatMap, first, map } from 'rxjs/operators'; 7 | import { isNotNull } from './operators'; 8 | import { ConnectionStore, WalletStore } from '@heavy-duty/wallet-adapter'; 9 | 10 | @Component({ 11 | selector: 'wa-home', 12 | template: ` 13 |
14 |

@heavy-duty/wallet-adapter example

15 |
16 | 17 |
18 |
19 |

Wallet details

20 | 21 | 33 | 34 |

35 | Selected provider: {{ walletName$ | async }} 36 | (READY) 37 |

38 |

Wallet Key: {{ publicKey$ | async }}

39 | 48 | 51 |
52 | 53 |
54 |

Transaction

55 | 56 |
57 | 58 | 59 |
60 | 61 |
62 | 63 | 64 |
65 | 66 | 67 | 68 | 71 | 72 |
73 |
74 | `, 75 | }) 76 | export class HomeComponent { 77 | readonly connection$ = this._connectionStore.connection$; 78 | readonly wallets$ = this._walletStore.wallets$; 79 | readonly wallet$ = this._walletStore.wallet$; 80 | readonly walletName$ = this.wallet$.pipe( 81 | map((wallet) => wallet?.adapter.name || null) 82 | ); 83 | readonly ready$ = this.wallet$.pipe( 84 | map( 85 | (wallet) => 86 | wallet && 87 | (wallet.adapter.readyState === WalletReadyState.Installed || 88 | wallet.adapter.readyState === WalletReadyState.Loadable) 89 | ) 90 | ); 91 | readonly connected$ = this._walletStore.connected$; 92 | readonly publicKey$ = this._walletStore.publicKey$; 93 | lamports = 0; 94 | recipient = ''; 95 | 96 | constructor( 97 | private readonly _connectionStore: ConnectionStore, 98 | private readonly _walletStore: WalletStore 99 | ) {} 100 | 101 | onConnect() { 102 | this._walletStore.connect().subscribe(); 103 | } 104 | 105 | onDisconnect() { 106 | this._walletStore.disconnect().subscribe(); 107 | } 108 | 109 | onSelectWallet(walletName: WalletName) { 110 | this._walletStore.selectWallet(walletName); 111 | } 112 | 113 | onSendTransaction(fromPubkey: PublicKey) { 114 | this.connection$ 115 | .pipe( 116 | first(), 117 | isNotNull, 118 | concatMap((connection) => 119 | from(defer(() => connection.getLatestBlockhash())).pipe( 120 | concatMap(({ blockhash, lastValidBlockHeight }) => 121 | this._walletStore.sendTransaction( 122 | new Transaction({ 123 | blockhash, 124 | feePayer: fromPubkey, 125 | lastValidBlockHeight, 126 | }).add( 127 | SystemProgram.transfer({ 128 | fromPubkey, 129 | toPubkey: new PublicKey(this.recipient), 130 | lamports: this.lamports, 131 | }) 132 | ), 133 | connection 134 | ) 135 | ) 136 | ) 137 | ) 138 | ) 139 | .subscribe({ 140 | next: (signature) => console.log(`Transaction sent (${signature})`), 141 | error: (error) => console.error(error), 142 | }); 143 | } 144 | 145 | onSignTransaction(fromPubkey: PublicKey) { 146 | this.connection$ 147 | .pipe( 148 | first(), 149 | isNotNull, 150 | concatMap((connection) => 151 | from(defer(() => connection.getLatestBlockhash())).pipe( 152 | map(({ blockhash, lastValidBlockHeight }) => 153 | new Transaction({ 154 | blockhash, 155 | feePayer: fromPubkey, 156 | lastValidBlockHeight 157 | }).add( 158 | SystemProgram.transfer({ 159 | fromPubkey, 160 | toPubkey: new PublicKey(this.recipient), 161 | lamports: this.lamports, 162 | }) 163 | ) 164 | ) 165 | ) 166 | ), 167 | concatMap((transaction) => { 168 | const signTransaction$ = 169 | this._walletStore.signTransaction(transaction); 170 | 171 | if (!signTransaction$) { 172 | return throwError( 173 | () => new Error('Sign transaction method is not defined') 174 | ); 175 | } 176 | 177 | return signTransaction$; 178 | }) 179 | ) 180 | .subscribe({ 181 | next: (transaction) => console.log('Transaction signed', transaction), 182 | error: (error) => console.error(error) 183 | }); 184 | } 185 | 186 | onSignAllTransactions(fromPubkey: PublicKey) { 187 | this.connection$ 188 | .pipe( 189 | first(), 190 | isNotNull, 191 | concatMap((connection) => 192 | from(defer(() => connection.getLatestBlockhash())).pipe( 193 | map(({ blockhash, lastValidBlockHeight }) => 194 | new Array(3).fill(0).map(() => 195 | new Transaction({ 196 | blockhash, 197 | feePayer: fromPubkey, 198 | lastValidBlockHeight 199 | }).add( 200 | SystemProgram.transfer({ 201 | fromPubkey, 202 | toPubkey: new PublicKey(this.recipient), 203 | lamports: this.lamports, 204 | }) 205 | ) 206 | ) 207 | ) 208 | ) 209 | ), 210 | concatMap((transactions) => { 211 | const signAllTransaction$ = 212 | this._walletStore.signAllTransactions(transactions); 213 | 214 | if (!signAllTransaction$) { 215 | return throwError( 216 | () => new Error('Sign all transactions method is not defined') 217 | ); 218 | } 219 | 220 | return signAllTransaction$; 221 | }) 222 | ) 223 | .subscribe({ 224 | next: (transactions) => console.log('Transactions signed', transactions), 225 | error: (error) => console.error(error) 226 | }); 227 | } 228 | 229 | onSignMessage() { 230 | const signMessage$ = this._walletStore.signMessage( 231 | new TextEncoder().encode('Hello world!') 232 | ); 233 | 234 | if (!signMessage$) { 235 | return console.error(new Error('Sign message method is not defined')); 236 | } 237 | 238 | signMessage$.pipe(first()).subscribe((signature) => { 239 | console.log(`Message signature: ${{ encode }.encode(signature)}`); 240 | }); 241 | } 242 | } 243 | -------------------------------------------------------------------------------- /apps/raw-wallet-adapter/src/app/operators/index.ts: -------------------------------------------------------------------------------- 1 | export * from './not-null'; 2 | -------------------------------------------------------------------------------- /apps/raw-wallet-adapter/src/app/operators/not-null.ts: -------------------------------------------------------------------------------- 1 | import { Observable } from 'rxjs'; 2 | import { filter } from 'rxjs/operators'; 3 | 4 | export const isNotNull = (source: Observable) => 5 | source.pipe(filter((item: T | null): item is T => item !== null)); 6 | -------------------------------------------------------------------------------- /apps/raw-wallet-adapter/src/assets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danmt/wallet-adapter-angular-sample/3dff199a052ce88077a0cc97d0c2467a24c14425/apps/raw-wallet-adapter/src/assets/.gitkeep -------------------------------------------------------------------------------- /apps/raw-wallet-adapter/src/environments/environment.prod.ts: -------------------------------------------------------------------------------- 1 | export const environment = { 2 | production: true, 3 | }; 4 | -------------------------------------------------------------------------------- /apps/raw-wallet-adapter/src/environments/environment.ts: -------------------------------------------------------------------------------- 1 | // This file can be replaced during build by using the `fileReplacements` array. 2 | // `ng build` replaces `environment.ts` with `environment.prod.ts`. 3 | // The list of file replacements can be found in `angular.json`. 4 | 5 | export const environment = { 6 | production: false, 7 | }; 8 | 9 | /* 10 | * For easier debugging in development mode, you can import the following file 11 | * to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`. 12 | * 13 | * This import should be commented out in production mode because it will have a negative impact 14 | * on performance if an error is thrown. 15 | */ 16 | // import 'zone.js/plugins/zone-error'; // Included with Angular CLI. 17 | -------------------------------------------------------------------------------- /apps/raw-wallet-adapter/src/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danmt/wallet-adapter-angular-sample/3dff199a052ce88077a0cc97d0c2467a24c14425/apps/raw-wallet-adapter/src/favicon.ico -------------------------------------------------------------------------------- /apps/raw-wallet-adapter/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | RawWalletAdapter 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /apps/raw-wallet-adapter/src/main.ts: -------------------------------------------------------------------------------- 1 | import { enableProdMode } from '@angular/core'; 2 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 3 | 4 | import { AppModule } from './app/app.module'; 5 | import { environment } from './environments/environment'; 6 | 7 | if (environment.production) { 8 | enableProdMode(); 9 | } 10 | 11 | platformBrowserDynamic() 12 | .bootstrapModule(AppModule) 13 | .catch((err) => console.error(err)); 14 | -------------------------------------------------------------------------------- /apps/raw-wallet-adapter/src/polyfills.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This file includes polyfills needed by Angular and is loaded before the app. 3 | * You can add your own extra polyfills to this file. 4 | * 5 | * This file is divided into 2 sections: 6 | * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers. 7 | * 2. Application imports. Files imported after ZoneJS that should be loaded before your main 8 | * file. 9 | * 10 | * The current setup is for so-called "evergreen" browsers; the last versions of browsers that 11 | * automatically update themselves. This includes recent versions of Safari, Chrome (including 12 | * Opera), Edge on the desktop, and iOS and Chrome on mobile. 13 | * 14 | * Learn more in https://angular.io/guide/browser-support 15 | */ 16 | 17 | /*************************************************************************************************** 18 | * BROWSER POLYFILLS 19 | */ 20 | 21 | /** 22 | * By default, zone.js will patch all possible macroTask and DomEvents 23 | * user can disable parts of macroTask/DomEvents patch by setting following flags 24 | * because those flags need to be set before `zone.js` being loaded, and webpack 25 | * will put import in the top of bundle, so user need to create a separate file 26 | * in this directory (for example: zone-flags.ts), and put the following flags 27 | * into that file, and then add the following code before importing zone.js. 28 | * import './zone-flags'; 29 | * 30 | * The flags allowed in zone-flags.ts are listed here. 31 | * 32 | * The following flags will work for all browsers. 33 | * 34 | * (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame 35 | * (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick 36 | * (window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames 37 | * 38 | * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js 39 | * with the following flag, it will bypass `zone.js` patch for IE/Edge 40 | * 41 | * (window as any).__Zone_enable_cross_context_check = true; 42 | * 43 | */ 44 | 45 | /*************************************************************************************************** 46 | * Zone JS is required by default for Angular itself. 47 | */ 48 | import 'zone.js'; // Included with Angular CLI. 49 | 50 | /*************************************************************************************************** 51 | * APPLICATION IMPORTS 52 | */ 53 | 54 | import { Buffer } from 'buffer'; 55 | (window as any).global = window; 56 | global.Buffer = global.Buffer || Buffer; 57 | (window as any).process = { 58 | version: '', 59 | }; 60 | -------------------------------------------------------------------------------- /apps/raw-wallet-adapter/src/styles.scss: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | 5 | /* You can add global styles to this file, and also import other style files */ 6 | -------------------------------------------------------------------------------- /apps/raw-wallet-adapter/src/test-setup.ts: -------------------------------------------------------------------------------- 1 | import 'jest-preset-angular/setup-jest'; 2 | -------------------------------------------------------------------------------- /apps/raw-wallet-adapter/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "types": [] 6 | }, 7 | "files": ["src/main.ts", "src/polyfills.ts"], 8 | "include": ["src/**/*.d.ts"], 9 | "exclude": ["**/*.test.ts", "**/*.spec.ts"] 10 | } 11 | -------------------------------------------------------------------------------- /apps/raw-wallet-adapter/tsconfig.editor.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "include": ["**/*.ts"], 4 | "compilerOptions": { 5 | "types": ["jest", "node"] 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /apps/raw-wallet-adapter/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "files": [], 4 | "include": [], 5 | "references": [ 6 | { 7 | "path": "./tsconfig.app.json" 8 | }, 9 | { 10 | "path": "./tsconfig.spec.json" 11 | }, 12 | { 13 | "path": "./tsconfig.editor.json" 14 | } 15 | ], 16 | "compilerOptions": { 17 | "target": "es2020", 18 | "forceConsistentCasingInFileNames": true, 19 | "strict": true, 20 | "noImplicitOverride": true, 21 | "noPropertyAccessFromIndexSignature": true, 22 | "noImplicitReturns": true, 23 | "noFallthroughCasesInSwitch": true 24 | }, 25 | "angularCompilerOptions": { 26 | "enableI18nLegacyMessageIdFormat": false, 27 | "strictInjectionParameters": true, 28 | "strictInputAccessModifiers": true, 29 | "strictTemplates": true 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /apps/raw-wallet-adapter/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "module": "commonjs", 6 | "types": ["jest", "node"] 7 | }, 8 | "files": ["src/test-setup.ts"], 9 | "include": ["jest.config.ts", "**/*.test.ts", "**/*.spec.ts", "**/*.d.ts"] 10 | } 11 | -------------------------------------------------------------------------------- /apps/raw-wallet-adapter/webpack.config.js: -------------------------------------------------------------------------------- 1 | module.exports = (config) => { 2 | config.resolve.fallback = { 3 | crypto: false, 4 | assert: false, 5 | stream: false 6 | }; 7 | 8 | return config; 9 | }; 10 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | const { getJestProjects } = require('@nrwl/jest'); 2 | 3 | module.exports = { 4 | projects: getJestProjects(), 5 | }; 6 | -------------------------------------------------------------------------------- /jest.preset.js: -------------------------------------------------------------------------------- 1 | const nxPreset = require('@nrwl/jest/preset'); 2 | 3 | module.exports = { ...nxPreset }; 4 | -------------------------------------------------------------------------------- /libs/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danmt/wallet-adapter-angular-sample/3dff199a052ce88077a0cc97d0c2467a24c14425/libs/.gitkeep -------------------------------------------------------------------------------- /nx.json: -------------------------------------------------------------------------------- 1 | { 2 | "npmScope": "wallet-adapter-test", 3 | "affected": { 4 | "defaultBase": "master" 5 | }, 6 | "implicitDependencies": { 7 | "package.json": { 8 | "dependencies": "*", 9 | "devDependencies": "*" 10 | }, 11 | ".eslintrc.json": "*" 12 | }, 13 | "tasksRunnerOptions": { 14 | "default": { 15 | "runner": "@nrwl/workspace/tasks-runners/default", 16 | "options": { 17 | "cacheableOperations": ["build", "lint", "test", "e2e"], 18 | "parallel": 1 19 | } 20 | } 21 | }, 22 | "targetDependencies": { 23 | "build": [ 24 | { 25 | "target": "build", 26 | "projects": "dependencies" 27 | } 28 | ] 29 | }, 30 | "generators": { 31 | "@nrwl/angular:application": { 32 | "style": "scss", 33 | "linter": "eslint", 34 | "unitTestRunner": "jest", 35 | "e2eTestRunner": "none" 36 | }, 37 | "@nrwl/angular:library": { 38 | "linter": "eslint", 39 | "unitTestRunner": "jest" 40 | }, 41 | "@nrwl/angular:component": { 42 | "style": "scss" 43 | } 44 | }, 45 | "$schema": "./node_modules/nx/schemas/nx-schema.json", 46 | "cli": { 47 | "defaultCollection": "@nrwl/angular" 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "wallet-adapter-test", 3 | "version": "0.0.0", 4 | "license": "MIT", 5 | "scripts": { 6 | "start": "nx serve", 7 | "build": "nx build", 8 | "test": "nx test", 9 | "postinstall": "ngcc --properties es2015 browser module main" 10 | }, 11 | "private": true, 12 | "dependencies": { 13 | "@angular/animations": "14.0.0", 14 | "@angular/cdk": "14.0.0", 15 | "@angular/common": "14.0.0", 16 | "@angular/compiler": "14.0.0", 17 | "@angular/core": "14.0.0", 18 | "@angular/forms": "14.0.0", 19 | "@angular/material": "14.0.0", 20 | "@angular/platform-browser": "14.0.0", 21 | "@angular/platform-browser-dynamic": "14.0.0", 22 | "@angular/router": "14.0.0", 23 | "@heavy-duty/wallet-adapter": "0.3.0-beta.1", 24 | "@heavy-duty/wallet-adapter-cdk": "^0.3.0-beta.1", 25 | "@heavy-duty/wallet-adapter-material": "^0.3.0-beta.1", 26 | "@ngrx/component": "14.0.0-beta.0", 27 | "@ngrx/component-store": "14.0.0-beta.0", 28 | "@nrwl/angular": "14.2.0-rc.2", 29 | "@solana/wallet-adapter-base": "0.9.5", 30 | "@solana/wallet-adapter-wallets": "0.15.5", 31 | "@solana/web3.js": "1.43.5", 32 | "bs58": "^5.0.0", 33 | "buffer": "^6.0.3", 34 | "rxjs": "7.5.2", 35 | "tslib": "^2.0.0", 36 | "zone.js": "0.11.4" 37 | }, 38 | "devDependencies": { 39 | "@angular-devkit/build-angular": "14.0.0", 40 | "@angular-eslint/eslint-plugin": "13.2.1", 41 | "@angular-eslint/eslint-plugin-template": "13.2.1", 42 | "@angular-eslint/template-parser": "13.2.1", 43 | "@angular/cli": "~14.0.0", 44 | "@angular/compiler-cli": "14.0.0", 45 | "@angular/language-service": "14.0.0", 46 | "@nrwl/cli": "14.2.0-rc.2", 47 | "@nrwl/eslint-plugin-nx": "14.2.0-rc.2", 48 | "@nrwl/jest": "14.2.0-rc.2", 49 | "@nrwl/linter": "14.2.0-rc.2", 50 | "@nrwl/workspace": "14.2.0-rc.2", 51 | "@types/jest": "27.0.2", 52 | "@types/node": "14.18.1", 53 | "@typescript-eslint/eslint-plugin": "5.24.0", 54 | "@typescript-eslint/parser": "5.24.0", 55 | "eslint": "8.2.0", 56 | "eslint-config-prettier": "8.1.0", 57 | "jest": "27.2.3", 58 | "jest-preset-angular": "11.0.0", 59 | "postcss": "^8.3.9", 60 | "postcss-import": "14.1.0", 61 | "postcss-preset-env": "7.5.0", 62 | "postcss-url": "10.1.3", 63 | "prettier": "^2.5.1", 64 | "tailwindcss": "^3.0.24", 65 | "ts-jest": "27.0.5", 66 | "ts-node": "~10.8.0", 67 | "typescript": "4.7.3" 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /tools/generators/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danmt/wallet-adapter-angular-sample/3dff199a052ce88077a0cc97d0c2467a24c14425/tools/generators/.gitkeep -------------------------------------------------------------------------------- /tools/tsconfig.tools.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.base.json", 3 | "compilerOptions": { 4 | "outDir": "../dist/out-tsc/tools", 5 | "rootDir": ".", 6 | "module": "commonjs", 7 | "target": "es5", 8 | "types": ["node"], 9 | "importHelpers": false 10 | }, 11 | "include": ["**/*.ts"] 12 | } 13 | -------------------------------------------------------------------------------- /tsconfig.base.json: -------------------------------------------------------------------------------- 1 | { 2 | "compileOnSave": false, 3 | "compilerOptions": { 4 | "rootDir": ".", 5 | "sourceMap": true, 6 | "declaration": false, 7 | "moduleResolution": "node", 8 | "emitDecoratorMetadata": true, 9 | "experimentalDecorators": true, 10 | "importHelpers": true, 11 | "target": "es2015", 12 | "module": "esnext", 13 | "lib": ["es2017", "dom"], 14 | "skipLibCheck": true, 15 | "skipDefaultLibCheck": true, 16 | "baseUrl": ".", 17 | "paths": {} 18 | }, 19 | "exclude": ["node_modules", "tmp"] 20 | } 21 | -------------------------------------------------------------------------------- /workspace.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "projects": { 4 | "material-wallet-adapter": "apps/material-wallet-adapter", 5 | "raw-wallet-adapter": "apps/raw-wallet-adapter" 6 | }, 7 | "$schema": "./node_modules/nx/schemas/workspace-schema.json" 8 | } 9 | --------------------------------------------------------------------------------