@monerium/sdk 1.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintignore +13 -0
- package/.eslintrc.cjs +20 -0
- package/.github/workflows/release-please.yml +30 -0
- package/.prettierignore +13 -0
- package/.prettierrc +6 -0
- package/CHANGELOG.md +31 -0
- package/README.md +93 -0
- package/package.json +40 -0
- package/src/app.d.ts +11 -0
- package/src/app.html +12 -0
- package/src/lib/client.ts +359 -0
- package/src/lib/config.ts +59 -0
- package/src/lib/index.ts +1 -0
- package/src/routes/index.svelte +32 -0
- package/src/routes/integration.svelte +45 -0
- package/static/favicon.png +0 -0
- package/svelte.config.js +19 -0
- package/test/index.test.ts +20 -0
- package/tsconfig.json +19 -0
- package/vite.config.js +14 -0
- package/vitest.config.ts +7 -0
package/.eslintignore
ADDED
package/.eslintrc.cjs
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
module.exports = {
|
|
2
|
+
root: true,
|
|
3
|
+
parser: '@typescript-eslint/parser',
|
|
4
|
+
extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended', 'prettier'],
|
|
5
|
+
plugins: ['svelte3', '@typescript-eslint'],
|
|
6
|
+
ignorePatterns: ['*.cjs'],
|
|
7
|
+
overrides: [{ files: ['*.svelte'], processor: 'svelte3/svelte3' }],
|
|
8
|
+
settings: {
|
|
9
|
+
'svelte3/typescript': () => require('typescript')
|
|
10
|
+
},
|
|
11
|
+
parserOptions: {
|
|
12
|
+
sourceType: 'module',
|
|
13
|
+
ecmaVersion: 2020
|
|
14
|
+
},
|
|
15
|
+
env: {
|
|
16
|
+
browser: true,
|
|
17
|
+
es2017: true,
|
|
18
|
+
node: true
|
|
19
|
+
}
|
|
20
|
+
};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
on:
|
|
2
|
+
push:
|
|
3
|
+
branches:
|
|
4
|
+
- main
|
|
5
|
+
name: release-please
|
|
6
|
+
jobs:
|
|
7
|
+
release-please:
|
|
8
|
+
runs-on: ubuntu-latest
|
|
9
|
+
steps:
|
|
10
|
+
- uses: google-github-actions/release-please-action@v3
|
|
11
|
+
id: release
|
|
12
|
+
with:
|
|
13
|
+
release-type: node
|
|
14
|
+
package-name: release-please-action
|
|
15
|
+
# The logic below handles the npm publication:
|
|
16
|
+
- uses: actions/checkout@v2
|
|
17
|
+
# these if statements ensure that a publication only occurs when
|
|
18
|
+
# a new release is created:
|
|
19
|
+
if: ${{ steps.release.outputs.release_created }}
|
|
20
|
+
- uses: actions/setup-node@v1
|
|
21
|
+
with:
|
|
22
|
+
node-version: 18
|
|
23
|
+
registry-url: 'https://registry.npmjs.org'
|
|
24
|
+
if: ${{ steps.release.outputs.release_created }}
|
|
25
|
+
- run: yarn install --frozen-lockfile
|
|
26
|
+
if: ${{ steps.release.outputs.release_created }}
|
|
27
|
+
- run: yarn publish
|
|
28
|
+
env:
|
|
29
|
+
NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}}
|
|
30
|
+
if: ${{ steps.release.outputs.release_created }}
|
package/.prettierignore
ADDED
package/.prettierrc
ADDED
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## [1.0.3](https://github.com/monerium/sdk/compare/v1.0.2...v1.0.3) (2022-10-12)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Bug Fixes
|
|
7
|
+
|
|
8
|
+
* use yarn instead of npm for pipeline ([046256b](https://github.com/monerium/sdk/commit/046256bda17856b20efd454c63ade47de90170b3))
|
|
9
|
+
|
|
10
|
+
## [1.0.2](https://github.com/monerium/sdk/compare/v1.0.1...v1.0.2) (2022-10-12)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
### Bug Fixes
|
|
14
|
+
|
|
15
|
+
* test if adding id:release will trigger npm publish ([2a091bf](https://github.com/monerium/sdk/commit/2a091bfddbacf8c724d78ca626ff91337b4cec0b))
|
|
16
|
+
|
|
17
|
+
## [1.0.1](https://github.com/monerium/sdk/compare/v1.0.0...v1.0.1) (2022-10-12)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
### Bug Fixes
|
|
21
|
+
|
|
22
|
+
* testing auto publish to npm ([77ed6a7](https://github.com/monerium/sdk/commit/77ed6a78d78e62bb22a247344267d390e699e297))
|
|
23
|
+
|
|
24
|
+
## 1.0.0 (2022-10-11)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
### Features
|
|
28
|
+
|
|
29
|
+
* add client class ([0948c05](https://github.com/monerium/sdk/commit/0948c0562e15f525471463b4104dd1a8bdf616f7))
|
|
30
|
+
* add monerium configuration ([792ce5e](https://github.com/monerium/sdk/commit/792ce5e6590931bedc837384869d38018c66afc2))
|
|
31
|
+
* **pipeline:** add release-please github action ([66a8819](https://github.com/monerium/sdk/commit/66a88190b417ebe44b847fd578311ef5c1b463a2))
|
package/README.md
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# @monerium/sdk
|
|
2
|
+
|
|
3
|
+
Everything you need to interact with Monerium.
|
|
4
|
+
|
|
5
|
+
_This package is in development. Please make sure to check if any future updates contain commits that may change the behaviour of your application before you upgrade._
|
|
6
|
+
|
|
7
|
+
## Authentication
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
import { MoneriumClient } from 'monerium-js';
|
|
11
|
+
|
|
12
|
+
const client = await MoneriumClient.create();
|
|
13
|
+
|
|
14
|
+
// Depending on the authentication method you want to use,
|
|
15
|
+
// make sure to pass the correct arguments to the `auth` method.
|
|
16
|
+
// Optional arguments can be omitted.
|
|
17
|
+
|
|
18
|
+
// --- BASIC Authentication --- //
|
|
19
|
+
|
|
20
|
+
await client.auth({ email: '<required>', password: '<required>' });
|
|
21
|
+
|
|
22
|
+
// --- BEARER PKCE Authentication --- //
|
|
23
|
+
|
|
24
|
+
// 1. Redirect to Monerium PKCE Authentication flow.
|
|
25
|
+
await client
|
|
26
|
+
.auth({
|
|
27
|
+
client_id: '<required>',
|
|
28
|
+
state: '<recommended>',
|
|
29
|
+
address: '<optional>',
|
|
30
|
+
redirect_uri: '<optional>',
|
|
31
|
+
scope: '<optional>'
|
|
32
|
+
})
|
|
33
|
+
.then(() => {
|
|
34
|
+
// store the `code_verifier` from `client.codeVerifier` for later.
|
|
35
|
+
sessionStorage.setItem('code_verifier', client.codeVerifier);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
// User will be redirected to the redirect_url with
|
|
39
|
+
// the code and the state in query parameters
|
|
40
|
+
// Make sure to compare the state from the response and the one you passed.
|
|
41
|
+
|
|
42
|
+
// 2. Redeem Code
|
|
43
|
+
const bearerProfile = await client.auth({
|
|
44
|
+
client_id: '<required>',
|
|
45
|
+
code: '<required>',
|
|
46
|
+
code_verifier: sessionStorage.getItem('code_verifier'),
|
|
47
|
+
redirect_uri: '<can be omitted if not set in request>',
|
|
48
|
+
scope: '<optional>'
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
// Note: In case steps 1 and 2 are executed in different environments,
|
|
52
|
+
// e.g. 1 in the browser and 2 on the server, you can pass a bearer
|
|
53
|
+
// profile in order to authenticate as shown below.
|
|
54
|
+
|
|
55
|
+
client.auth(bearerProfile);
|
|
56
|
+
|
|
57
|
+
// --- BEARER Client Authentication --- //
|
|
58
|
+
|
|
59
|
+
await client.auth({ client_id: '<required>', client_secret: '<required>', scope: '<optional>' });
|
|
60
|
+
|
|
61
|
+
// --- Client Attributes --- //
|
|
62
|
+
|
|
63
|
+
client.authContext;
|
|
64
|
+
client.bearerProfile;
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Demo
|
|
68
|
+
|
|
69
|
+
To check out the demo site for this pacakge, run the following commands:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
yarn install
|
|
73
|
+
yarn dev
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Developing
|
|
77
|
+
|
|
78
|
+
If you want to make any code contributions, make sure to run the following commands before you pr them:
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
yarn format
|
|
82
|
+
yarn lint
|
|
83
|
+
yarn test
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## Publishing
|
|
87
|
+
|
|
88
|
+
If you want to modify and publish the package yourself, run the following commands:
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
yarn package
|
|
92
|
+
yarn publish
|
|
93
|
+
```
|
package/package.json
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@monerium/sdk",
|
|
3
|
+
"version": "1.0.4",
|
|
4
|
+
"private": false,
|
|
5
|
+
"scripts": {
|
|
6
|
+
"dev": "vite dev",
|
|
7
|
+
"test": "vitest",
|
|
8
|
+
"build": "vite build",
|
|
9
|
+
"package": "svelte-kit package",
|
|
10
|
+
"preview": "vite preview",
|
|
11
|
+
"check": "svelte-check --tsconfig ./tsconfig.json",
|
|
12
|
+
"check:watch": "svelte-check --tsconfig ./tsconfig.json --watch",
|
|
13
|
+
"lint": "prettier --check --plugin-search-dir=. . && eslint .",
|
|
14
|
+
"format": "prettier --write --plugin-search-dir=. ."
|
|
15
|
+
},
|
|
16
|
+
"devDependencies": {
|
|
17
|
+
"@sveltejs/adapter-auto": "next",
|
|
18
|
+
"@sveltejs/kit": "next",
|
|
19
|
+
"@typescript-eslint/eslint-plugin": "^5.27.0",
|
|
20
|
+
"@typescript-eslint/parser": "^5.27.0",
|
|
21
|
+
"eslint": "^8.16.0",
|
|
22
|
+
"eslint-config-prettier": "^8.3.0",
|
|
23
|
+
"eslint-plugin-svelte3": "^4.0.0",
|
|
24
|
+
"prettier": "^2.6.2",
|
|
25
|
+
"prettier-plugin-svelte": "^2.7.0",
|
|
26
|
+
"svelte": "^3.44.0",
|
|
27
|
+
"svelte-check": "^2.7.1",
|
|
28
|
+
"svelte-preprocess": "^4.10.6",
|
|
29
|
+
"tslib": "^2.3.1",
|
|
30
|
+
"typescript": "^4.7.4",
|
|
31
|
+
"vite": "^3.0.0",
|
|
32
|
+
"vitest": "^0.21.0"
|
|
33
|
+
},
|
|
34
|
+
"type": "module",
|
|
35
|
+
"dependencies": {
|
|
36
|
+
"@0xsequence/multicall": "^0.40.5",
|
|
37
|
+
"ethers": "^5.6.9",
|
|
38
|
+
"oauth-pkce": "^0.0.6"
|
|
39
|
+
}
|
|
40
|
+
}
|
package/src/app.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// See https://kit.svelte.dev/docs/types#app
|
|
2
|
+
// for information about these interfaces
|
|
3
|
+
// and what to do when importing types
|
|
4
|
+
declare namespace App {
|
|
5
|
+
// interface Locals {}
|
|
6
|
+
// interface Platform {}
|
|
7
|
+
// interface PrivateEnv {}
|
|
8
|
+
// interface PublicEnv {}
|
|
9
|
+
// interface Session {}
|
|
10
|
+
// interface Stuff {}
|
|
11
|
+
}
|
package/src/app.html
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8" />
|
|
5
|
+
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
|
|
6
|
+
<meta name="viewport" content="width=device-width" />
|
|
7
|
+
%sveltekit.head%
|
|
8
|
+
</head>
|
|
9
|
+
<body>
|
|
10
|
+
<div>%sveltekit.body%</div>
|
|
11
|
+
</body>
|
|
12
|
+
</html>
|
|
@@ -0,0 +1,359 @@
|
|
|
1
|
+
import { MONERIUM_CONFIG } from './config';
|
|
2
|
+
import type { ethers } from 'ethers';
|
|
3
|
+
import { providers } from '@0xsequence/multicall';
|
|
4
|
+
import getPkce from 'oauth-pkce';
|
|
5
|
+
import pjson from './../../package.json';
|
|
6
|
+
|
|
7
|
+
type SupportedProvider = ethers.providers.Web3Provider | ethers.providers.JsonRpcProvider;
|
|
8
|
+
|
|
9
|
+
type CurrencyCode = 'eur' | 'gbp' | 'usd' | 'isk';
|
|
10
|
+
|
|
11
|
+
type Network = 'mainnet' | 'ropsten' | 'rinkeby' | 'kovan' | 'goerli' | 'mumbai';
|
|
12
|
+
|
|
13
|
+
type Chain = 'ethereum' | 'polygon';
|
|
14
|
+
interface BasicRedeem {
|
|
15
|
+
email: string;
|
|
16
|
+
password: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
interface PKCERequest {
|
|
20
|
+
client_id: string;
|
|
21
|
+
code_challenge?: string;
|
|
22
|
+
code_challenge_method?: string;
|
|
23
|
+
response_type?: string;
|
|
24
|
+
redirect_uri?: string;
|
|
25
|
+
state?: string;
|
|
26
|
+
address?: string;
|
|
27
|
+
scope?: string;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
interface PKCERedeem {
|
|
31
|
+
client_id: string;
|
|
32
|
+
code: string;
|
|
33
|
+
code_verifier: string;
|
|
34
|
+
grant_type?: string;
|
|
35
|
+
redirect_uri?: string;
|
|
36
|
+
scope?: string;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
interface ClientRedeem {
|
|
40
|
+
client_id: string;
|
|
41
|
+
client_secret: string;
|
|
42
|
+
scope?: string;
|
|
43
|
+
grant_type?: string;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
interface BearerProfile {
|
|
47
|
+
access_token: string;
|
|
48
|
+
token_type: string;
|
|
49
|
+
expires_in: number;
|
|
50
|
+
refresh_token: string;
|
|
51
|
+
profile: string;
|
|
52
|
+
userId: string;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
interface AuthContext {
|
|
56
|
+
userId: string;
|
|
57
|
+
email: string;
|
|
58
|
+
name: string;
|
|
59
|
+
roles: [string];
|
|
60
|
+
auth: { method: string; subject: string; verified: boolean };
|
|
61
|
+
defaultProfile: string;
|
|
62
|
+
profiles: [{ id: string; type: string; name: string; perms: [string] }];
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
interface CurrencyAccounts {
|
|
66
|
+
network: Network;
|
|
67
|
+
chain: Chain;
|
|
68
|
+
currency: CurrencyCode;
|
|
69
|
+
}
|
|
70
|
+
interface ConnectWalletPayload {
|
|
71
|
+
address: string;
|
|
72
|
+
message: string;
|
|
73
|
+
signature: string;
|
|
74
|
+
accounts: CurrencyAccounts[];
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
interface PlaceOrderPayloadByAccount {
|
|
78
|
+
accountId: string;
|
|
79
|
+
}
|
|
80
|
+
interface PlaceOrderPayloadByAddress {
|
|
81
|
+
address: string;
|
|
82
|
+
currency: CurrencyCode;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
interface CounterpartDetailsIndividual {
|
|
86
|
+
firstName: string;
|
|
87
|
+
lastName: string;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
interface CounterpartDetailsCorporation {
|
|
91
|
+
companyName: string;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
interface CounterpartIdentifierBase {
|
|
95
|
+
standard: 'iban' | 'scan';
|
|
96
|
+
}
|
|
97
|
+
interface CounterpartIdentifierIban extends CounterpartIdentifierBase {
|
|
98
|
+
standard: 'iban';
|
|
99
|
+
iban: string;
|
|
100
|
+
}
|
|
101
|
+
interface CounterpartIdentifierScan extends CounterpartIdentifierBase {
|
|
102
|
+
standard: 'scan';
|
|
103
|
+
sortCode: string;
|
|
104
|
+
accountNumber: string;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
type CounterpartIdentifier = CounterpartIdentifierIban | CounterpartIdentifierScan;
|
|
108
|
+
|
|
109
|
+
type CounterpartDetails = CounterpartDetailsIndividual | CounterpartDetailsCorporation;
|
|
110
|
+
interface Counterpart {
|
|
111
|
+
identifier: CounterpartIdentifier;
|
|
112
|
+
details: CounterpartDetails;
|
|
113
|
+
}
|
|
114
|
+
interface PlaceOrderPayloadBase {
|
|
115
|
+
kind: 'redeem' | 'issue';
|
|
116
|
+
amount: string;
|
|
117
|
+
signature: string;
|
|
118
|
+
counterpart: Counterpart;
|
|
119
|
+
message: string;
|
|
120
|
+
memo?: string;
|
|
121
|
+
supportingDocumentId?: string;
|
|
122
|
+
chain?: string;
|
|
123
|
+
network?: string;
|
|
124
|
+
|
|
125
|
+
// TODO: https://monerium.dev/api-docs#operation/post-profile-orders
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
type PlaceOrderPayload = PlaceOrderPayloadBase &
|
|
129
|
+
(PlaceOrderPayloadByAccount | PlaceOrderPayloadByAddress);
|
|
130
|
+
|
|
131
|
+
const order: PlaceOrderPayload = {
|
|
132
|
+
kind: 'redeem',
|
|
133
|
+
amount: '1',
|
|
134
|
+
signature: 'sign',
|
|
135
|
+
message: 'TODO',
|
|
136
|
+
accountId: 'TODO',
|
|
137
|
+
counterpart: {
|
|
138
|
+
identifier: {
|
|
139
|
+
standard: 'iban',
|
|
140
|
+
iban: '1234'
|
|
141
|
+
},
|
|
142
|
+
details: {
|
|
143
|
+
firstName: 'Name',
|
|
144
|
+
lastName: 'Nameson'
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
interface SupportingDocumentPayload {
|
|
150
|
+
file: File;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
export class MoneriumClient {
|
|
154
|
+
#env!: { base: string; web: string };
|
|
155
|
+
#provider?: ethers.providers.Provider;
|
|
156
|
+
#signer?: ethers.Signer;
|
|
157
|
+
#authPayload?: string;
|
|
158
|
+
codeVerifier?: string;
|
|
159
|
+
|
|
160
|
+
bearerProfile?: BearerProfile;
|
|
161
|
+
authContext?: AuthContext;
|
|
162
|
+
|
|
163
|
+
// --- Constructor --- //
|
|
164
|
+
|
|
165
|
+
static async create(env: 'production' | 'sandbox' = 'sandbox', provider?: SupportedProvider) {
|
|
166
|
+
const client = new MoneriumClient();
|
|
167
|
+
|
|
168
|
+
await client.#initialize(env, provider);
|
|
169
|
+
|
|
170
|
+
return client;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
async #initialize(env: 'production' | 'sandbox', provider?: SupportedProvider) {
|
|
174
|
+
this.#env = MONERIUM_CONFIG.environments[env];
|
|
175
|
+
|
|
176
|
+
if (provider) {
|
|
177
|
+
this.#provider = new providers.MulticallProvider(provider);
|
|
178
|
+
this.#signer = provider.getSigner();
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// --- Private Helper Methods --- //
|
|
183
|
+
|
|
184
|
+
async #api(
|
|
185
|
+
method: string,
|
|
186
|
+
resource: string,
|
|
187
|
+
data?:
|
|
188
|
+
| PKCERequest
|
|
189
|
+
| PKCERedeem
|
|
190
|
+
| ClientRedeem
|
|
191
|
+
| ConnectWalletPayload
|
|
192
|
+
| PlaceOrderPayload
|
|
193
|
+
| SupportingDocumentPayload,
|
|
194
|
+
isFormEncoded?: boolean
|
|
195
|
+
) {
|
|
196
|
+
const res = await fetch(`${this.#env.base}/${resource}`, {
|
|
197
|
+
method,
|
|
198
|
+
headers: {
|
|
199
|
+
// To understand SDK adoption and correlate issues to specific versions.
|
|
200
|
+
'User-Agent': 'monerium-sdk/' + pjson.version,
|
|
201
|
+
'content-type': isFormEncoded ? 'application/x-www-form-urlencoded' : 'application/json',
|
|
202
|
+
Authorization: this.#authPayload || ''
|
|
203
|
+
},
|
|
204
|
+
body:
|
|
205
|
+
data && isFormEncoded
|
|
206
|
+
? new URLSearchParams(data as unknown as Record<string, string>)
|
|
207
|
+
: JSON.stringify(data)
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
if (res.status >= 200 && res.status <= 299) {
|
|
211
|
+
return await res.json();
|
|
212
|
+
} else {
|
|
213
|
+
return new Error(res.statusText);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
#isPKCERequest(
|
|
218
|
+
args: PKCERequest | BearerProfile | BasicRedeem | PKCERedeem | ClientRedeem
|
|
219
|
+
): args is PKCERequest {
|
|
220
|
+
return (args as PKCERequest).client_id != undefined && (args as PKCERedeem)?.code === undefined;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
#isBearerProfileAuth(
|
|
224
|
+
args: BearerProfile | BasicRedeem | PKCERedeem | ClientRedeem
|
|
225
|
+
): args is BearerProfile {
|
|
226
|
+
return (args as BearerProfile).access_token != undefined;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
#isBasicAuth(args: BasicRedeem | PKCERedeem | ClientRedeem): args is BasicRedeem {
|
|
230
|
+
return (args as BasicRedeem).password != undefined;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
#isPKCEAuth(args: PKCERedeem | ClientRedeem): args is PKCERedeem {
|
|
234
|
+
return (args as PKCERedeem).code != undefined;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
#isClientAuth(args: ClientRedeem): args is ClientRedeem {
|
|
238
|
+
return (args as ClientRedeem).client_secret != undefined;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
// --- Public Methods --- //
|
|
242
|
+
|
|
243
|
+
async auth(args: PKCERequest | BearerProfile | BasicRedeem | PKCERedeem | ClientRedeem) {
|
|
244
|
+
if (this.#isPKCERequest(args)) {
|
|
245
|
+
const { verifier, challenge } = await new Promise<{ verifier: string; challenge: string }>(
|
|
246
|
+
(resolve) => {
|
|
247
|
+
getPkce(43, (error, { verifier, challenge }) => {
|
|
248
|
+
if (error) throw error;
|
|
249
|
+
resolve({ verifier, challenge });
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
);
|
|
253
|
+
|
|
254
|
+
const requestData = {
|
|
255
|
+
client_id: args?.client_id,
|
|
256
|
+
code_challenge: challenge,
|
|
257
|
+
code_challenge_method: 'S256',
|
|
258
|
+
response_type: 'code',
|
|
259
|
+
redirect_uri: args.redirect_uri || '',
|
|
260
|
+
scope: args.scope || 'orders:read',
|
|
261
|
+
state: args.state || '',
|
|
262
|
+
address: args.address || ''
|
|
263
|
+
};
|
|
264
|
+
this.codeVerifier = verifier;
|
|
265
|
+
this.#authPayload = ' ';
|
|
266
|
+
|
|
267
|
+
if (typeof window !== 'undefined') {
|
|
268
|
+
return window.location.replace(
|
|
269
|
+
`${this.#env.base}/auth?${new URLSearchParams(requestData).toString()}`
|
|
270
|
+
);
|
|
271
|
+
}
|
|
272
|
+
return new Error('Something went wrong. Please contact the Monerium Support team.');
|
|
273
|
+
} else {
|
|
274
|
+
if (this.#isBearerProfileAuth(args)) {
|
|
275
|
+
this.bearerProfile = args;
|
|
276
|
+
this.#authPayload = this.bearerProfile && `Bearer ${this.bearerProfile.access_token}`;
|
|
277
|
+
} else if (this.#isBasicAuth(args)) {
|
|
278
|
+
const bufferObj = Buffer.from(`${args.email}:${args.password}`, 'utf8');
|
|
279
|
+
this.#authPayload = `Basic ${bufferObj.toString('base64')}`;
|
|
280
|
+
} else if (this.#isPKCEAuth(args)) {
|
|
281
|
+
const redeemData: PKCERedeem = {
|
|
282
|
+
client_id: args.client_id,
|
|
283
|
+
code: args.code,
|
|
284
|
+
redirect_uri: args.redirect_uri,
|
|
285
|
+
grant_type: 'authorization_code',
|
|
286
|
+
code_verifier: args.code_verifier,
|
|
287
|
+
scope: args.scope || 'orders:read'
|
|
288
|
+
};
|
|
289
|
+
|
|
290
|
+
this.bearerProfile = await this.#api('post', 'auth/token', redeemData, true);
|
|
291
|
+
this.#authPayload = this.bearerProfile && `Bearer ${this.bearerProfile.access_token}`;
|
|
292
|
+
} else if (this.#isClientAuth(args)) {
|
|
293
|
+
const redeemData: ClientRedeem = {
|
|
294
|
+
client_id: args.client_id,
|
|
295
|
+
client_secret: args.client_secret,
|
|
296
|
+
grant_type: 'client_credentials',
|
|
297
|
+
scope: args.scope || 'orders:read'
|
|
298
|
+
};
|
|
299
|
+
|
|
300
|
+
this.bearerProfile = await this.#api('post', 'auth/token', redeemData, true);
|
|
301
|
+
this.#authPayload = this.bearerProfile && `Bearer ${this.bearerProfile.access_token}`;
|
|
302
|
+
} else {
|
|
303
|
+
return new Error('Something went wrong. Please contact the Monerium Support team.');
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
this.authContext = await this.getAuthContext();
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
async getAuthContext() {
|
|
311
|
+
return await this.#api('get', 'auth/context');
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
async getProfile(profileId: string) {
|
|
315
|
+
return await this.#api('get', `profiles/${profileId}`);
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
async getOrders(profileId?: string) {
|
|
319
|
+
if (profileId) {
|
|
320
|
+
return await this.#api('get', `profiles/${profileId}/orders`);
|
|
321
|
+
} else {
|
|
322
|
+
return await this.#api('get', `orders`);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
async getOrder(orderId: string) {
|
|
327
|
+
return await this.#api('get', `orders/${orderId}`);
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
async getBalances(profileId?: string) {
|
|
331
|
+
if (profileId) {
|
|
332
|
+
return await this.#api('get', `profiles/${profileId}/balances`);
|
|
333
|
+
} else {
|
|
334
|
+
return await this.#api('get', 'balances');
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
async getTokens() {
|
|
338
|
+
return await this.#api('get', 'tokens');
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
async connectWallet(profileId: string, body: ConnectWalletPayload) {
|
|
342
|
+
return await this.#api('post', `profiles/${profileId}/address`, body);
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
async placeOrder(body?: PlaceOrderPayload, profileId?: string) {
|
|
346
|
+
if (profileId) {
|
|
347
|
+
return await this.#api('post', `profiles/${profileId}/orders`, body);
|
|
348
|
+
} else {
|
|
349
|
+
return await this.#api('post', `orders`, body);
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
async uploadSupportingDocument(body: SupportingDocumentPayload) {
|
|
354
|
+
return await this.#api('post', `files/supporting-document`, body, true);
|
|
355
|
+
}
|
|
356
|
+
// orderNotifications websockets?
|
|
357
|
+
// https://monerium.dev/api-docs#operation/profile-orders-notifications
|
|
358
|
+
// https://monerium.dev/api-docs#operation/orders-notifications
|
|
359
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
type Tokens = {
|
|
2
|
+
EUR: string;
|
|
3
|
+
GBP: string;
|
|
4
|
+
USD: string;
|
|
5
|
+
ISK: string;
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
type TokenConfig = {
|
|
9
|
+
contract: string;
|
|
10
|
+
ens?: string;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
type MoneriumConfig = {
|
|
14
|
+
deployments: { [chainId: number]: { [Property in keyof Tokens]: TokenConfig } };
|
|
15
|
+
environments: {
|
|
16
|
+
[env: string]: { base: string; web: string };
|
|
17
|
+
};
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export const MONERIUM_CONFIG: MoneriumConfig = {
|
|
21
|
+
deployments: {
|
|
22
|
+
1: {
|
|
23
|
+
EUR: {
|
|
24
|
+
contract: '0x3231cb76718cdef2155fc47b5286d82e6eda273f',
|
|
25
|
+
ens: 'eur.monerium.eth'
|
|
26
|
+
},
|
|
27
|
+
GBP: {
|
|
28
|
+
contract: '0x7ba92741bf2a568abc6f1d3413c58c6e0244f8fd',
|
|
29
|
+
ens: 'gbp.monerium.eth'
|
|
30
|
+
},
|
|
31
|
+
USD: {
|
|
32
|
+
contract: '0xbc5142e0cc5eb16b47c63b0f033d4c2480853a52',
|
|
33
|
+
ens: 'usd.monerium.eth'
|
|
34
|
+
},
|
|
35
|
+
ISK: {
|
|
36
|
+
contract: '0xc642549743a93674cf38d6431f75d6443f88e3e2',
|
|
37
|
+
ens: 'isk.monerium.eth'
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
4: {
|
|
41
|
+
EUR: {
|
|
42
|
+
contract: '0x25c13fc529dc4afe4d488bd1f2ee5e1ec4918e0b'
|
|
43
|
+
},
|
|
44
|
+
GBP: {
|
|
45
|
+
contract: '0x01df10e345d0364d3a5b8422a66af6305803bd1e'
|
|
46
|
+
},
|
|
47
|
+
USD: {
|
|
48
|
+
contract: '0x09c0a236e1227500f495cb0731c4af69b49639a5'
|
|
49
|
+
},
|
|
50
|
+
ISK: {
|
|
51
|
+
contract: '0x0c9d7a0d8bf4bc9d15f577bbf650ebc8044a71db'
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
environments: {
|
|
56
|
+
production: { base: 'https://api.monerium.app', web: 'https://monerium.app' },
|
|
57
|
+
sandbox: { base: 'https://api.monerium.dev', web: 'https://sandbox.monerium.dev' }
|
|
58
|
+
}
|
|
59
|
+
};
|
package/src/lib/index.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { MoneriumClient } from './client';
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { onMount } from 'svelte';
|
|
3
|
+
import { MoneriumClient } from 'monerium-js';
|
|
4
|
+
|
|
5
|
+
let client: MoneriumClient;
|
|
6
|
+
|
|
7
|
+
onMount(async () => {
|
|
8
|
+
client = await MoneriumClient.create();
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
// client Credential:
|
|
12
|
+
// id: 654c9c30-44d3-11ed-adac-b2efc0e6677d
|
|
13
|
+
// secret: ac474b7cdc111973aa080b0428ba3a824e82119bee8f65875b4aba0d42416dff
|
|
14
|
+
|
|
15
|
+
async function authenticate() {
|
|
16
|
+
await client.auth({
|
|
17
|
+
client_id: '654c9c30-44d3-11ed-adac-b2efc0e6677d',
|
|
18
|
+
// partner_name: 'piedpiper',
|
|
19
|
+
redirect_uri: 'http://localhost:5173/integration'
|
|
20
|
+
}).then(() => {
|
|
21
|
+
if (typeof window !== "undefined" && client?.codeVerifier) {
|
|
22
|
+
sessionStorage.setItem("code_verifier", client.codeVerifier)
|
|
23
|
+
console.log('%cadding codeVerifier to session storage', 'color:white; padding: 30px; background-color: darkgreen', client.codeVerifier)
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
}
|
|
29
|
+
</script>
|
|
30
|
+
|
|
31
|
+
<h1>This is a demo of the Monerium JavaScript SDK.</h1>
|
|
32
|
+
<button on:click={authenticate}>Login</button>
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { afterUpdate, onMount } from 'svelte';
|
|
3
|
+
import { MoneriumClient } from 'monerium-js';
|
|
4
|
+
|
|
5
|
+
let client: MoneriumClient;
|
|
6
|
+
let codeVerifier: string;
|
|
7
|
+
let authContext = undefined;
|
|
8
|
+
const urlParams = typeof window !== "undefined" ? new URLSearchParams(window.location.search) : undefined;
|
|
9
|
+
|
|
10
|
+
console.log('%curlParams', 'color:white; padding: 30px; background-color: darkgreen', urlParams?.get('code'))
|
|
11
|
+
|
|
12
|
+
onMount(async () => {
|
|
13
|
+
client = await MoneriumClient.create();
|
|
14
|
+
codeVerifier = sessionStorage?.getItem("code_verifier") || '' ;
|
|
15
|
+
console.log('%ccodeVerifier from session storage', 'color:white; padding: 30px; background-color: darkgreen', codeVerifier)
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
afterUpdate(() => authContext = client?.authContext)
|
|
19
|
+
|
|
20
|
+
// client Credential:
|
|
21
|
+
// id: 654c9c30-44d3-11ed-adac-b2efc0e6677d
|
|
22
|
+
// secret: ac474b7cdc111973aa080b0428ba3a824e82119bee8f65875b4aba0d42416dff
|
|
23
|
+
async function authenticate() {
|
|
24
|
+
client.auth({
|
|
25
|
+
code: urlParams?.get('code') || '',
|
|
26
|
+
grant_type: 'authorization_code',
|
|
27
|
+
code_verifier: codeVerifier,
|
|
28
|
+
client_id: '654c9c30-44d3-11ed-adac-b2efc0e6677d',
|
|
29
|
+
// partner_name: 'piedpiper',
|
|
30
|
+
redirect_uri: 'http://localhost:5173/integration'
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
async function getBalances() {
|
|
35
|
+
client.getBalances();
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
</script>
|
|
39
|
+
|
|
40
|
+
<h1>Partner redirect demo page</h1>
|
|
41
|
+
<p>{authContext}</p>
|
|
42
|
+
<button on:click={authenticate}>authenticate</button>
|
|
43
|
+
<button on:click={getBalances}>get balances</button>
|
|
44
|
+
|
|
45
|
+
|
|
Binary file
|
package/svelte.config.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import adapter from '@sveltejs/adapter-auto';
|
|
2
|
+
import preprocess from 'svelte-preprocess';
|
|
3
|
+
|
|
4
|
+
/** @type {import('@sveltejs/kit').Config} */
|
|
5
|
+
const config = {
|
|
6
|
+
// Consult https://github.com/sveltejs/svelte-preprocess
|
|
7
|
+
// for more information about preprocessors
|
|
8
|
+
preprocess: preprocess(),
|
|
9
|
+
|
|
10
|
+
kit: {
|
|
11
|
+
adapter: adapter(),
|
|
12
|
+
package: {
|
|
13
|
+
files: (file) => !file.startsWith('demo'),
|
|
14
|
+
exports: (file) => file === 'index.js'
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export default config;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { MoneriumClient } from '../src/lib/index';
|
|
3
|
+
|
|
4
|
+
const bearerClientArgs = {
|
|
5
|
+
client_id: '1234567890abcdef',
|
|
6
|
+
client_secret: '1234567890abcdef1234567890abcdef'
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
describe('Monerium Client Tests', () => {
|
|
10
|
+
it('should authenticate with client secret', async () => {
|
|
11
|
+
const client = await MoneriumClient.create();
|
|
12
|
+
|
|
13
|
+
await client.auth(bearerClientArgs);
|
|
14
|
+
|
|
15
|
+
expect(client.authContext).toHaveProperty('email', 'simon.ibars@request.network');
|
|
16
|
+
}, 100000);
|
|
17
|
+
|
|
18
|
+
it.todo('should authenticate with PKCE flow');
|
|
19
|
+
it.todo('should authenticate with user credentials');
|
|
20
|
+
});
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"extends": "./.svelte-kit/tsconfig.json",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"allowJs": true,
|
|
5
|
+
"checkJs": true,
|
|
6
|
+
"esModuleInterop": true,
|
|
7
|
+
"forceConsistentCasingInFileNames": true,
|
|
8
|
+
"resolveJsonModule": true,
|
|
9
|
+
"skipLibCheck": true,
|
|
10
|
+
"sourceMap": true,
|
|
11
|
+
"strict": true,
|
|
12
|
+
"paths": {
|
|
13
|
+
"$lib": ["src/lib"],
|
|
14
|
+
"$lib/*": ["src/lib/*"],
|
|
15
|
+
"monerium-js": ["src/lib/index.ts"],
|
|
16
|
+
"monerium-js/*": ["src/lib/*"]
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
package/vite.config.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { sveltekit } from '@sveltejs/kit/vite';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
|
|
4
|
+
/** @type {import('vite').UserConfig} */
|
|
5
|
+
const config = {
|
|
6
|
+
plugins: [sveltekit()],
|
|
7
|
+
resolve: {
|
|
8
|
+
alias: {
|
|
9
|
+
'monerium-js': path.resolve('src/lib')
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export default config;
|