@coinflowlabs/angular 0.0.3 → 0.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/ng-package.json +7 -0
- package/package.json +9 -17
- package/src/lib/coinflow-iframe.component.ts +63 -0
- package/src/lib/coinflow-purchase-history.component.ts +9 -0
- package/src/lib/coinflow-purchase-protection.component.ts +9 -0
- package/src/lib/coinflow-purchase.component.ts +37 -0
- package/src/lib/coinflow-withdraw-history.component.ts +9 -0
- package/src/lib/coinflow-withdraw.component.ts +36 -0
- package/src/lib/common/CoinflowLibMessageHandlers.ts +188 -0
- package/src/lib/common/CoinflowTypes.ts +403 -0
- package/src/lib/common/CoinflowUtils.ts +269 -0
- package/{public-api.d.ts → src/public-api.ts} +4 -0
- package/tsconfig.lib.json +14 -0
- package/tsconfig.lib.prod.json +10 -0
- package/tsconfig.spec.json +14 -0
- package/esm2022/coinflowlabs-angular.mjs +0 -5
- package/esm2022/lib/coinflow-iframe.component.mjs +0 -67
- package/esm2022/lib/coinflow-purchase-history.component.mjs +0 -16
- package/esm2022/lib/coinflow-purchase-protection.component.mjs +0 -16
- package/esm2022/lib/coinflow-purchase.component.mjs +0 -32
- package/esm2022/lib/coinflow-withdraw-history.component.mjs +0 -16
- package/esm2022/lib/coinflow-withdraw.component.mjs +0 -32
- package/esm2022/lib/common/CoinflowLibMessageHandlers.mjs +0 -127
- package/esm2022/lib/common/CoinflowTypes.mjs +0 -13
- package/esm2022/lib/common/CoinflowUtils.mjs +0 -173
- package/esm2022/lib/common/index.mjs +0 -4
- package/esm2022/public-api.mjs +0 -10
- package/fesm2022/coinflowlabs-angular.mjs +0 -486
- package/fesm2022/coinflowlabs-angular.mjs.map +0 -1
- package/index.d.ts +0 -5
- package/lib/coinflow-iframe.component.d.ts +0 -17
- package/lib/coinflow-purchase-history.component.d.ts +0 -5
- package/lib/coinflow-purchase-protection.component.d.ts +0 -5
- package/lib/coinflow-purchase.component.d.ts +0 -10
- package/lib/coinflow-withdraw-history.component.d.ts +0 -5
- package/lib/coinflow-withdraw.component.d.ts +0 -10
- package/lib/common/CoinflowLibMessageHandlers.d.ts +0 -21
- package/lib/common/CoinflowTypes.d.ts +0 -287
- package/lib/common/CoinflowUtils.d.ts +0 -21
- /package/{lib/common/index.d.ts → src/lib/common/index.ts} +0 -0
package/ng-package.json
ADDED
package/package.json
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@coinflowlabs/angular",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.4",
|
|
4
|
+
"scripts": {
|
|
5
|
+
"clean": "rimraf ../../dist && rimraf ./src/lib/common",
|
|
6
|
+
"build": "npm run codegen && ng build coinflowlabs",
|
|
7
|
+
"codegen": "cp -r ../../../lib-common/src/ ./src/lib/common/"
|
|
8
|
+
},
|
|
4
9
|
"peerDependencies": {
|
|
5
10
|
"@angular/common": "^17.3.0",
|
|
6
11
|
"@angular/core": "^17.3.0",
|
|
@@ -9,7 +14,7 @@
|
|
|
9
14
|
"bs58": "~5.0.0"
|
|
10
15
|
},
|
|
11
16
|
"dependencies": {
|
|
12
|
-
"tslib": "^2.
|
|
17
|
+
"tslib": "^2.6.2"
|
|
13
18
|
},
|
|
14
19
|
"peerDependenciesMeta": {
|
|
15
20
|
"@coinflowlabs/lib-common": {
|
|
@@ -22,18 +27,5 @@
|
|
|
22
27
|
"optional": true
|
|
23
28
|
}
|
|
24
29
|
},
|
|
25
|
-
"sideEffects": false
|
|
26
|
-
|
|
27
|
-
"typings": "index.d.ts",
|
|
28
|
-
"exports": {
|
|
29
|
-
"./package.json": {
|
|
30
|
-
"default": "./package.json"
|
|
31
|
-
},
|
|
32
|
-
".": {
|
|
33
|
-
"types": "./index.d.ts",
|
|
34
|
-
"esm2022": "./esm2022/coinflowlabs-angular.mjs",
|
|
35
|
-
"esm": "./esm2022/coinflowlabs-angular.mjs",
|
|
36
|
-
"default": "./fesm2022/coinflowlabs-angular.mjs"
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
}
|
|
30
|
+
"sideEffects": false
|
|
31
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Component,
|
|
3
|
+
ElementRef,
|
|
4
|
+
HostListener,
|
|
5
|
+
Input,
|
|
6
|
+
ViewChild,
|
|
7
|
+
} from '@angular/core';
|
|
8
|
+
import {
|
|
9
|
+
CoinflowIFrameProps,
|
|
10
|
+
CoinflowUtils,
|
|
11
|
+
IFrameMessageHandlers,
|
|
12
|
+
handleIFrameMessage,
|
|
13
|
+
} from './common';
|
|
14
|
+
import {DomSanitizer, SafeResourceUrl} from '@angular/platform-browser';
|
|
15
|
+
|
|
16
|
+
@Component({
|
|
17
|
+
selector: 'lib-coinflow-iframe',
|
|
18
|
+
standalone: true,
|
|
19
|
+
imports: [],
|
|
20
|
+
template: ` <iframe
|
|
21
|
+
width="100%"
|
|
22
|
+
height="100%"
|
|
23
|
+
#iframe
|
|
24
|
+
scrolling="{{ iframeProps?.handleHeightChange ? 'no' : 'yes' }}"
|
|
25
|
+
allow="payment;camera"
|
|
26
|
+
title="withdraw"
|
|
27
|
+
frameBorder="0"
|
|
28
|
+
[src]="dynamicUrl"
|
|
29
|
+
></iframe>`,
|
|
30
|
+
})
|
|
31
|
+
export class CoinflowIFrameComponent {
|
|
32
|
+
@Input() iframeProps!: CoinflowIFrameProps;
|
|
33
|
+
@Input() messageHandlers!: IFrameMessageHandlers;
|
|
34
|
+
|
|
35
|
+
dynamicUrl?: SafeResourceUrl;
|
|
36
|
+
@ViewChild('iframe') iframe?: ElementRef<HTMLIFrameElement>;
|
|
37
|
+
|
|
38
|
+
constructor(private sanitizer: DomSanitizer) {}
|
|
39
|
+
|
|
40
|
+
ngOnInit() {
|
|
41
|
+
const coinflowUrl = CoinflowUtils.getCoinflowUrl(this.iframeProps);
|
|
42
|
+
this.dynamicUrl =
|
|
43
|
+
this.sanitizer.bypassSecurityTrustResourceUrl(coinflowUrl);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
@HostListener('window:message', ['$event']) onPostMessage(event: any) {
|
|
47
|
+
if (
|
|
48
|
+
!event.origin.includes(
|
|
49
|
+
CoinflowUtils.getCoinflowBaseUrl(this.iframeProps.env)
|
|
50
|
+
)
|
|
51
|
+
)
|
|
52
|
+
return;
|
|
53
|
+
|
|
54
|
+
const promise = handleIFrameMessage(event.data, this.messageHandlers);
|
|
55
|
+
if (!promise) return;
|
|
56
|
+
promise.then(this.sendMessage.bind(this));
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
sendMessage(message: string) {
|
|
60
|
+
if (!this.iframe || !this.iframe.nativeElement) return;
|
|
61
|
+
this.iframe.nativeElement.contentWindow!.postMessage(message, '*');
|
|
62
|
+
}
|
|
63
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import {Component, Input} from '@angular/core';
|
|
2
|
+
import {CoinflowIFrameComponent} from './coinflow-iframe.component';
|
|
3
|
+
import {
|
|
4
|
+
CoinflowIFrameProps,
|
|
5
|
+
CoinflowPurchaseProps,
|
|
6
|
+
IFrameMessageHandlers,
|
|
7
|
+
getHandlers,
|
|
8
|
+
getWalletPubkey,
|
|
9
|
+
CoinflowUtils,
|
|
10
|
+
} from './common';
|
|
11
|
+
|
|
12
|
+
@Component({
|
|
13
|
+
selector: 'lib-coinflow-purchase',
|
|
14
|
+
standalone: true,
|
|
15
|
+
imports: [CoinflowIFrameComponent],
|
|
16
|
+
template:
|
|
17
|
+
' <lib-coinflow-iframe ng-if="iframeProps && messageHandlers" [iframeProps]="iframeProps!" [messageHandlers]="messageHandlers!"></lib-coinflow-iframe> ',
|
|
18
|
+
})
|
|
19
|
+
export class CoinflowPurchaseComponent {
|
|
20
|
+
@Input() purchaseProps!: CoinflowPurchaseProps;
|
|
21
|
+
iframeProps?: CoinflowIFrameProps;
|
|
22
|
+
messageHandlers?: IFrameMessageHandlers;
|
|
23
|
+
|
|
24
|
+
ngOnInit() {
|
|
25
|
+
const walletPubkey = getWalletPubkey(this.purchaseProps);
|
|
26
|
+
this.messageHandlers = getHandlers(this.purchaseProps);
|
|
27
|
+
this.messageHandlers.handleHeightChange =
|
|
28
|
+
this.purchaseProps.handleHeightChange;
|
|
29
|
+
|
|
30
|
+
this.iframeProps = {
|
|
31
|
+
...this.purchaseProps,
|
|
32
|
+
walletPubkey,
|
|
33
|
+
route: `/purchase/${this.purchaseProps?.merchantId}`,
|
|
34
|
+
transaction: CoinflowUtils.getTransaction(this.purchaseProps),
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import {Component, Input} from '@angular/core';
|
|
2
|
+
import {
|
|
3
|
+
CoinflowIFrameProps,
|
|
4
|
+
CoinflowWithdrawProps,
|
|
5
|
+
IFrameMessageHandlers,
|
|
6
|
+
getHandlers,
|
|
7
|
+
getWalletPubkey,
|
|
8
|
+
} from './common';
|
|
9
|
+
import {CoinflowIFrameComponent} from './coinflow-iframe.component';
|
|
10
|
+
|
|
11
|
+
@Component({
|
|
12
|
+
selector: 'lib-coinflow-withdraw',
|
|
13
|
+
standalone: true,
|
|
14
|
+
imports: [CoinflowIFrameComponent],
|
|
15
|
+
template:
|
|
16
|
+
' <lib-coinflow-iframe ng-if="iframeProps && messageHandlers" [iframeProps]="iframeProps!" [messageHandlers]="messageHandlers!"></lib-coinflow-iframe> ',
|
|
17
|
+
})
|
|
18
|
+
export class CoinflowWithdrawComponent {
|
|
19
|
+
@Input() withdrawProps!: CoinflowWithdrawProps;
|
|
20
|
+
iframeProps?: CoinflowIFrameProps;
|
|
21
|
+
messageHandlers?: IFrameMessageHandlers;
|
|
22
|
+
|
|
23
|
+
ngOnInit() {
|
|
24
|
+
const walletPubkey = getWalletPubkey(this.withdrawProps);
|
|
25
|
+
this.messageHandlers = getHandlers(this.withdrawProps);
|
|
26
|
+
this.messageHandlers.handleHeightChange =
|
|
27
|
+
this.withdrawProps.handleHeightChange;
|
|
28
|
+
|
|
29
|
+
this.iframeProps = {
|
|
30
|
+
...this.withdrawProps,
|
|
31
|
+
walletPubkey,
|
|
32
|
+
route: `/withdraw/${this.withdrawProps?.merchantId}`,
|
|
33
|
+
transaction: undefined,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CoinflowPurchaseProps,
|
|
3
|
+
EthWallet,
|
|
4
|
+
NearWallet,
|
|
5
|
+
SolanaWallet,
|
|
6
|
+
} from './CoinflowTypes';
|
|
7
|
+
import {CoinflowUtils} from './CoinflowUtils';
|
|
8
|
+
import {Transaction, VersionedTransaction} from '@solana/web3.js';
|
|
9
|
+
import * as web3 from '@solana/web3.js';
|
|
10
|
+
import base58 from 'bs58';
|
|
11
|
+
|
|
12
|
+
export type WalletCall = {method: IFrameMessageMethods; data: string};
|
|
13
|
+
|
|
14
|
+
export interface IFrameMessageHandlers {
|
|
15
|
+
handleSendTransaction: (transaction: string) => Promise<string>;
|
|
16
|
+
handleSignMessage?: (message: string) => Promise<string>;
|
|
17
|
+
handleSignTransaction?: (transaction: string) => Promise<string>;
|
|
18
|
+
handleHeightChange?: (height: string) => void;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
enum IFrameMessageMethods {
|
|
22
|
+
SignMessage = 'signMessage',
|
|
23
|
+
SignTransaction = 'signTransaction',
|
|
24
|
+
SendTransaction = 'sendTransaction',
|
|
25
|
+
HeightChange = 'heightChange',
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function getWalletPubkey({
|
|
29
|
+
wallet,
|
|
30
|
+
}: Pick<CoinflowPurchaseProps, 'wallet'>): string | null | undefined {
|
|
31
|
+
if ('publicKey' in wallet) {
|
|
32
|
+
return wallet.publicKey!.toString();
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if ('address' in wallet) {
|
|
36
|
+
return wallet.address;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if ('accountId' in wallet) {
|
|
40
|
+
return wallet.accountId;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export function handleIFrameMessage(
|
|
47
|
+
rawMessage: string,
|
|
48
|
+
handlers: IFrameMessageHandlers
|
|
49
|
+
): Promise<string> | void {
|
|
50
|
+
let walletCall: WalletCall;
|
|
51
|
+
try {
|
|
52
|
+
walletCall = JSON.parse(rawMessage);
|
|
53
|
+
if (!('method' in walletCall) || !('data' in walletCall)) return;
|
|
54
|
+
} catch (e) {
|
|
55
|
+
console.error('handleIFrameMessage JSON parse', e);
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const {data, method} = walletCall;
|
|
60
|
+
switch (method) {
|
|
61
|
+
case IFrameMessageMethods.SignMessage:
|
|
62
|
+
if (!handlers.handleSignMessage) return;
|
|
63
|
+
return handlers.handleSignMessage(data);
|
|
64
|
+
case IFrameMessageMethods.SignTransaction:
|
|
65
|
+
if (!handlers.handleSignTransaction) return;
|
|
66
|
+
return handlers.handleSignTransaction(data);
|
|
67
|
+
case IFrameMessageMethods.SendTransaction:
|
|
68
|
+
return handlers.handleSendTransaction(data);
|
|
69
|
+
case IFrameMessageMethods.HeightChange:
|
|
70
|
+
if (!handlers.handleHeightChange) return;
|
|
71
|
+
return handlers.handleHeightChange(data);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
console.warn(
|
|
75
|
+
`Didn't expect to get here, handleIFrameMessage method:${method} is not one of ${Object.values(IFrameMessageMethods)}`
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export function getHandlers({
|
|
80
|
+
wallet,
|
|
81
|
+
blockchain,
|
|
82
|
+
}: Pick<CoinflowPurchaseProps, 'wallet' | 'blockchain'>): Omit<
|
|
83
|
+
IFrameMessageHandlers,
|
|
84
|
+
'handleHeightChange'
|
|
85
|
+
> {
|
|
86
|
+
return CoinflowUtils.byBlockchain(blockchain, {
|
|
87
|
+
solana: () => getSolanaWalletHandlers({wallet}),
|
|
88
|
+
near: () => getNearWalletHandlers({wallet}),
|
|
89
|
+
eth: () => getEvmWalletHandlers({wallet}),
|
|
90
|
+
polygon: () => getEvmWalletHandlers({wallet}),
|
|
91
|
+
base: () => getEvmWalletHandlers({wallet}),
|
|
92
|
+
})();
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function getSolanaWalletHandlers({
|
|
96
|
+
wallet,
|
|
97
|
+
}: Pick<CoinflowPurchaseProps, 'wallet'>): Omit<
|
|
98
|
+
IFrameMessageHandlers,
|
|
99
|
+
'handleHeightChange'
|
|
100
|
+
> {
|
|
101
|
+
return {
|
|
102
|
+
handleSendTransaction: async (transaction: string) => {
|
|
103
|
+
const tx = getSolanaTransaction(transaction);
|
|
104
|
+
return (wallet as SolanaWallet).sendTransaction(tx);
|
|
105
|
+
},
|
|
106
|
+
handleSignMessage: async (message: string) => {
|
|
107
|
+
const signMessage = (wallet as SolanaWallet).signMessage;
|
|
108
|
+
if (!signMessage) {
|
|
109
|
+
throw new Error('signMessage is not supported by this wallet');
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const signedMessage = await signMessage(
|
|
113
|
+
new TextEncoder().encode(message)
|
|
114
|
+
);
|
|
115
|
+
return base58.encode(signedMessage);
|
|
116
|
+
},
|
|
117
|
+
handleSignTransaction: async (transaction: string) => {
|
|
118
|
+
const signTransaction = (wallet as SolanaWallet).signTransaction;
|
|
119
|
+
if (!signTransaction) {
|
|
120
|
+
throw new Error('signTransaction is not supported by this wallet');
|
|
121
|
+
}
|
|
122
|
+
const tx = getSolanaTransaction(transaction);
|
|
123
|
+
const signedTransaction = await signTransaction(tx);
|
|
124
|
+
return base58.encode(
|
|
125
|
+
signedTransaction.serialize({
|
|
126
|
+
requireAllSignatures: false,
|
|
127
|
+
verifySignatures: false,
|
|
128
|
+
})
|
|
129
|
+
);
|
|
130
|
+
},
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
function getSolanaTransaction(
|
|
135
|
+
data: string
|
|
136
|
+
): Transaction | VersionedTransaction {
|
|
137
|
+
if (!web3)
|
|
138
|
+
throw new Error(
|
|
139
|
+
'@solana/web3.js is not defined. Please install @solana/web3.js into your project'
|
|
140
|
+
);
|
|
141
|
+
|
|
142
|
+
if (!base58)
|
|
143
|
+
throw new Error(
|
|
144
|
+
'bs58 is not defined. Please install bs58 into your project'
|
|
145
|
+
);
|
|
146
|
+
|
|
147
|
+
const parsedUInt8Array = base58.decode(data);
|
|
148
|
+
const vtx = web3.VersionedTransaction.deserialize(parsedUInt8Array);
|
|
149
|
+
if (vtx.version === 'legacy') return web3.Transaction.from(parsedUInt8Array);
|
|
150
|
+
return vtx;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function getNearWalletHandlers({
|
|
154
|
+
wallet,
|
|
155
|
+
}: Pick<CoinflowPurchaseProps, 'wallet'>): Omit<
|
|
156
|
+
IFrameMessageHandlers,
|
|
157
|
+
'handleHeightChange'
|
|
158
|
+
> {
|
|
159
|
+
const nearWallet = wallet as NearWallet;
|
|
160
|
+
return {
|
|
161
|
+
handleSendTransaction: async (transaction: string) => {
|
|
162
|
+
const action = JSON.parse(Buffer.from(transaction, 'base64').toString());
|
|
163
|
+
const executionOutcome = await nearWallet.signAndSendTransaction(action);
|
|
164
|
+
if (!executionOutcome) throw new Error('Transaction did not send');
|
|
165
|
+
const {transaction: transactionResult} = executionOutcome;
|
|
166
|
+
return transactionResult.hash;
|
|
167
|
+
},
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
function getEvmWalletHandlers({
|
|
172
|
+
wallet,
|
|
173
|
+
}: Pick<CoinflowPurchaseProps, 'wallet'>): Omit<
|
|
174
|
+
IFrameMessageHandlers,
|
|
175
|
+
'handleHeightChange'
|
|
176
|
+
> {
|
|
177
|
+
const evmWallet = wallet as EthWallet;
|
|
178
|
+
return {
|
|
179
|
+
handleSendTransaction: async (transaction: string) => {
|
|
180
|
+
const tx = JSON.parse(Buffer.from(transaction, 'base64').toString());
|
|
181
|
+
const {hash} = await evmWallet.sendTransaction(tx);
|
|
182
|
+
return hash;
|
|
183
|
+
},
|
|
184
|
+
handleSignMessage: async (message: string) => {
|
|
185
|
+
return evmWallet.signMessage(message);
|
|
186
|
+
},
|
|
187
|
+
};
|
|
188
|
+
}
|