@rockerone/xprnkit 0.3.0
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/LICENSE +21 -0
- package/README.md +1100 -0
- package/build/components/identity/index.d.ts +4 -0
- package/build/components/identity/index.js +4 -0
- package/build/components/identity/xprn-avatar.d.ts +8 -0
- package/build/components/identity/xprn-avatar.js +23 -0
- package/build/components/identity/xprn-identity.d.ts +9 -0
- package/build/components/identity/xprn-identity.js +30 -0
- package/build/components/identity/xprn-session-actor.d.ts +4 -0
- package/build/components/identity/xprn-session-actor.js +13 -0
- package/build/components/identity/xprn-session-name.d.ts +4 -0
- package/build/components/identity/xprn-session-name.js +14 -0
- package/build/components/index.d.ts +5 -0
- package/build/components/index.js +5 -0
- package/build/components/swap/index.d.ts +46 -0
- package/build/components/swap/index.js +9 -0
- package/build/components/swap/xprn-swap-button.d.ts +5 -0
- package/build/components/swap/xprn-swap-button.js +21 -0
- package/build/components/swap/xprn-swap-field.d.ts +6 -0
- package/build/components/swap/xprn-swap-field.js +69 -0
- package/build/components/swap/xprn-swap-fields-group.d.ts +6 -0
- package/build/components/swap/xprn-swap-fields-group.js +16 -0
- package/build/components/swap/xprn-swap-fields.d.ts +4 -0
- package/build/components/swap/xprn-swap-fields.js +10 -0
- package/build/components/swap/xprn-swap-layout.d.ts +7 -0
- package/build/components/swap/xprn-swap-layout.js +21 -0
- package/build/components/swap/xprn-swap-markets-selector.d.ts +4 -0
- package/build/components/swap/xprn-swap-markets-selector.js +31 -0
- package/build/components/swap/xprn-swap-markets.d.ts +8 -0
- package/build/components/swap/xprn-swap-markets.js +93 -0
- package/build/components/swap/xprn-swap-pair-selector.d.ts +7 -0
- package/build/components/swap/xprn-swap-pair-selector.js +37 -0
- package/build/components/swap/xprn-swap-provider.d.ts +35 -0
- package/build/components/swap/xprn-swap-provider.js +187 -0
- package/build/components/swap/xprn-swap-side-button.d.ts +6 -0
- package/build/components/swap/xprn-swap-side-button.js +22 -0
- package/build/components/swap/xprn-swap.d.ts +9 -0
- package/build/components/swap/xprn-swap.js +12 -0
- package/build/components/ui/dropdown.d.ts +27 -0
- package/build/components/ui/dropdown.js +36 -0
- package/build/components/ui/input.d.ts +5 -0
- package/build/components/ui/input.js +8 -0
- package/build/components/ui/select.d.ts +13 -0
- package/build/components/ui/select.js +27 -0
- package/build/components/xprn-container.d.ts +9 -0
- package/build/components/xprn-container.js +15 -0
- package/build/components/xprn-session.d.ts +11 -0
- package/build/components/xprn-session.js +21 -0
- package/build/components/xprn-transaction.d.ts +23 -0
- package/build/components/xprn-transaction.js +58 -0
- package/build/global.css +1138 -0
- package/build/index.d.ts +5 -0
- package/build/index.js +3 -0
- package/build/interfaces/proton_wrap.d.ts +141 -0
- package/build/interfaces/proton_wrap.js +81 -0
- package/build/interfaces/service-status.d.ts +1 -0
- package/build/interfaces/service-status.js +1 -0
- package/build/interfaces/transaction-error-message.d.ts +5 -0
- package/build/interfaces/transaction-error-message.js +1 -0
- package/build/lib/utils.d.ts +2 -0
- package/build/lib/utils.js +5 -0
- package/build/providers/XPRNProvider.d.ts +59 -0
- package/build/providers/XPRNProvider.js +336 -0
- package/build/utils/index.d.ts +2 -0
- package/build/utils/index.js +2 -0
- package/build/utils/token-precision.d.ts +1 -0
- package/build/utils/token-precision.js +22 -0
- package/build/utils/transaction-errors.d.ts +2 -0
- package/build/utils/transaction-errors.js +15 -0
- package/package.json +49 -0
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import * as AvatarPrimitive from "@radix-ui/react-avatar";
|
|
3
|
+
declare const XPRNAvatarWrapper: React.ForwardRefExoticComponent<Omit<AvatarPrimitive.AvatarProps & React.RefAttributes<HTMLSpanElement>, "ref"> & React.RefAttributes<HTMLSpanElement>>;
|
|
4
|
+
declare const XPRNAvatarImage: React.ForwardRefExoticComponent<Omit<AvatarPrimitive.AvatarImageProps & React.RefAttributes<HTMLImageElement>, "ref"> & React.RefAttributes<HTMLImageElement>>;
|
|
5
|
+
declare const XPRNAvatarFallback: React.ForwardRefExoticComponent<Omit<AvatarPrimitive.AvatarFallbackProps & React.RefAttributes<HTMLSpanElement>, "ref"> & React.RefAttributes<HTMLSpanElement>>;
|
|
6
|
+
type XPRNAvatarProps = React.HTMLAttributes<HTMLDivElement>;
|
|
7
|
+
declare const XPRNAvatar: React.FunctionComponent<XPRNAvatarProps>;
|
|
8
|
+
export { XPRNAvatarWrapper, XPRNAvatar, XPRNAvatarImage, XPRNAvatarFallback };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import * as AvatarPrimitive from "@radix-ui/react-avatar";
|
|
5
|
+
import { cn } from "./../../lib/utils";
|
|
6
|
+
const XPRNAvatarWrapper = React.forwardRef(({ className, ...props }, ref) => (_jsx(AvatarPrimitive.Root, { ref: ref, className: cn("relative flex h-10 w-10 shrink-0 overflow-hidden rounded-full", className), ...props })));
|
|
7
|
+
XPRNAvatarWrapper.displayName = AvatarPrimitive.Root.displayName;
|
|
8
|
+
const XPRNAvatarImage = React.forwardRef(({ className, ...props }, ref) => (_jsx(AvatarPrimitive.Image, { ref: ref, className: cn("aspect-square h-full w-full", className), ...props })));
|
|
9
|
+
XPRNAvatarImage.displayName = AvatarPrimitive.Image.displayName;
|
|
10
|
+
const XPRNAvatarFallback = React.forwardRef(({ className, ...props }, ref) => (_jsx(AvatarPrimitive.Fallback, { ref: ref, className: cn("flex h-full w-full items-center justify-center rounded-full ", className), ...props })));
|
|
11
|
+
XPRNAvatarFallback.displayName = AvatarPrimitive.Fallback.displayName;
|
|
12
|
+
import classNames from "classnames";
|
|
13
|
+
import { useXPRN } from "../../providers/XPRNProvider";
|
|
14
|
+
const XPRNAvatar = ({ className, ...props }) => {
|
|
15
|
+
const { profile, session } = useXPRN();
|
|
16
|
+
const rootClasses = classNames({
|
|
17
|
+
[`${className}`]: className,
|
|
18
|
+
});
|
|
19
|
+
if (!session)
|
|
20
|
+
return;
|
|
21
|
+
return (_jsxs(XPRNAvatarWrapper, { className: rootClasses, ...props, children: [_jsx(XPRNAvatarFallback, { children: session.auth.actor.toString()[0] }), profile && profile.avatar && (_jsx(XPRNAvatarImage, { src: `data:image/png;base64,${profile.avatar}`, sizes: "" }))] }));
|
|
22
|
+
};
|
|
23
|
+
export { XPRNAvatarWrapper, XPRNAvatar, XPRNAvatarImage, XPRNAvatarFallback };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
type XPRNIdentityProps = React.HTMLAttributes<HTMLDivElement> & {
|
|
3
|
+
showLogout?: boolean;
|
|
4
|
+
activeSessionClassName?: string;
|
|
5
|
+
dropdownClassName?: string;
|
|
6
|
+
avatarClassName?: string;
|
|
7
|
+
};
|
|
8
|
+
export declare const XPRNIdentity: React.FunctionComponent<XPRNIdentityProps>;
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
+
import classNames from "classnames";
|
|
4
|
+
import * as React from "react";
|
|
5
|
+
import { XPRNAvatar } from "./xprn-avatar";
|
|
6
|
+
import { XPRNSessionActor } from "./xprn-session-actor";
|
|
7
|
+
import { XPRNSessionName } from "./xprn-session-name";
|
|
8
|
+
import { useXPRN } from "../../providers/XPRNProvider";
|
|
9
|
+
import { XPRNConnectButton } from "./../xprn-session";
|
|
10
|
+
import { DropdownMenu, DropdownMenuContent, DropdownMenuTrigger, } from "./../ui/dropdown";
|
|
11
|
+
export const XPRNIdentity = ({ children, className, showLogout, activeSessionClassName, dropdownClassName, avatarClassName, }) => {
|
|
12
|
+
const rootClasses = classNames({
|
|
13
|
+
"grid grid-cols-[min-content,1fr] gap-4 items-center inline": true,
|
|
14
|
+
[`${className}`]: className,
|
|
15
|
+
});
|
|
16
|
+
const activeSessionClasses = classNames({
|
|
17
|
+
"flex flex-row items-center gap-2": true,
|
|
18
|
+
[`${activeSessionClassName}`]: activeSessionClassName,
|
|
19
|
+
});
|
|
20
|
+
const dropdownClasses = classNames({
|
|
21
|
+
"flex flex-col items-center gap-2": true,
|
|
22
|
+
[`${dropdownClassName}`]: dropdownClassName,
|
|
23
|
+
});
|
|
24
|
+
const { session, profile, disconnect, authentication } = useXPRN();
|
|
25
|
+
const handleDisconnect = React.useCallback((e) => {
|
|
26
|
+
e.preventDefault();
|
|
27
|
+
disconnect();
|
|
28
|
+
}, [disconnect]);
|
|
29
|
+
return (_jsx(_Fragment, { children: session ? (_jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { className: "inline w-auto flex-grow-0", children: _jsxs("div", { className: activeSessionClasses, children: [_jsx("div", { className: "w-10 h-10", children: _jsx(XPRNAvatar, { className: avatarClassName }) }), _jsxs("div", { className: "flex flex-col", children: [_jsx(XPRNSessionName, { className: "text-md font-bold" }), _jsxs("div", { className: "flex gap-2", children: [_jsx(XPRNSessionActor, { className: "text-md" }), showLogout && (_jsx("a", { href: "#", className: "underline", onClick: e => handleDisconnect(e), children: "Log out" }))] })] })] }) }), children && (_jsx(DropdownMenuContent, { className: dropdownClasses, children: children }))] })) : (_jsx(XPRNConnectButton, { className: rootClasses, children: "Connect" })) }));
|
|
30
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import classNames from 'classnames';
|
|
4
|
+
import { useXPRN } from '../../providers/XPRNProvider';
|
|
5
|
+
export const XPRNSessionActor = ({ children, className }) => {
|
|
6
|
+
const { session } = useXPRN();
|
|
7
|
+
const rootClasses = classNames({
|
|
8
|
+
[`${className}`]: className,
|
|
9
|
+
});
|
|
10
|
+
if (!session)
|
|
11
|
+
return _jsx(_Fragment, {});
|
|
12
|
+
return _jsxs("h3", { className: `${rootClasses}`, children: ["@", session.auth.actor.toString()] });
|
|
13
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import classNames from "classnames";
|
|
4
|
+
import { useXPRN } from "../../providers/XPRNProvider";
|
|
5
|
+
export const XPRNSessionName = ({ children, className, }) => {
|
|
6
|
+
const { profile, authentication } = useXPRN();
|
|
7
|
+
const rootClasses = classNames({
|
|
8
|
+
"flex gap-2 items-center justify-center": true,
|
|
9
|
+
[`${className}`]: className,
|
|
10
|
+
});
|
|
11
|
+
if (!profile)
|
|
12
|
+
return _jsx(_Fragment, {});
|
|
13
|
+
return (_jsxs("div", { className: `${rootClasses}`, children: [_jsxs("h3", { children: ["@", profile.displayName.toString()] }), _jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className: "lucide lucide-badge-check", children: [_jsx("path", { d: "M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z" }), _jsx("path", { d: "m9 12 2 2 4-4" })] }), authentication && (_jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className: "lucide lucide-id-card", children: [_jsx("path", { d: "M16 10h2" }), _jsx("path", { d: "M16 14h2" }), _jsx("path", { d: "M6.17 15a3 3 0 0 1 5.66 0" }), _jsx("circle", { cx: "9", cy: "11", r: "2" }), _jsx("rect", { x: "2", y: "5", width: "20", height: "14", rx: "2" })] }))] }));
|
|
14
|
+
};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { LinkSession } from '@proton/web-sdk';
|
|
2
|
+
export type XPRNMarketProviderResult = {
|
|
3
|
+
pair: string;
|
|
4
|
+
baseToken: string;
|
|
5
|
+
baseContract: string;
|
|
6
|
+
basePrecision: number;
|
|
7
|
+
quoteToken: string;
|
|
8
|
+
quoteContract: string;
|
|
9
|
+
quotePrecision: number;
|
|
10
|
+
minBuy: number;
|
|
11
|
+
minSell: number;
|
|
12
|
+
askName: string;
|
|
13
|
+
bidName: string;
|
|
14
|
+
ask: number;
|
|
15
|
+
bid: number;
|
|
16
|
+
lastPrice: number;
|
|
17
|
+
baseTransactionMemo?: string;
|
|
18
|
+
quoteTransactionMemo?: string;
|
|
19
|
+
};
|
|
20
|
+
export type XPRNSwapSide = 'buy' | 'sell';
|
|
21
|
+
export type XPRNMarketProvider = {
|
|
22
|
+
endpoint: string;
|
|
23
|
+
name: string;
|
|
24
|
+
default?: boolean;
|
|
25
|
+
parse: (results: any[]) => XPRNMarketProviderResult[];
|
|
26
|
+
getTransaction: (swapPair: XPRNMarketProviderResult, volume: number, price: number, side: XPRNSwapSide, session?: LinkSession) => any[];
|
|
27
|
+
};
|
|
28
|
+
export type XPRNMarketProviderQuoteFilter = {
|
|
29
|
+
baseSymbol?: string;
|
|
30
|
+
quoteSymbol?: string;
|
|
31
|
+
};
|
|
32
|
+
export type XPRNSwapValues = {
|
|
33
|
+
base: number;
|
|
34
|
+
quote: number;
|
|
35
|
+
volume: number;
|
|
36
|
+
lastMutated: "base" | "quote";
|
|
37
|
+
};
|
|
38
|
+
export * from './xprn-swap-provider';
|
|
39
|
+
export * from './xprn-swap-markets-selector';
|
|
40
|
+
export * from './xprn-swap-pair-selector';
|
|
41
|
+
export * from './xprn-swap-layout';
|
|
42
|
+
export * from './xprn-swap-field';
|
|
43
|
+
export * from './xprn-swap-fields';
|
|
44
|
+
export * from './xprn-swap-fields-group';
|
|
45
|
+
export * from './xprn-swap-side-button';
|
|
46
|
+
export * from './xprn-swap';
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export * from './xprn-swap-provider';
|
|
2
|
+
export * from './xprn-swap-markets-selector';
|
|
3
|
+
export * from './xprn-swap-pair-selector';
|
|
4
|
+
export * from './xprn-swap-layout';
|
|
5
|
+
export * from './xprn-swap-field';
|
|
6
|
+
export * from './xprn-swap-fields';
|
|
7
|
+
export * from './xprn-swap-fields-group';
|
|
8
|
+
export * from './xprn-swap-side-button';
|
|
9
|
+
export * from './xprn-swap';
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import React from "react";
|
|
4
|
+
import classNames from "classnames";
|
|
5
|
+
import { XPRNTransaction, } from "../xprn-transaction";
|
|
6
|
+
import { useXPRNSwap } from "./xprn-swap-provider";
|
|
7
|
+
export const XPRNSwapButton = ({ children, className, }) => {
|
|
8
|
+
const { currentSwapPair, swapTransaction, swapSide } = useXPRNSwap();
|
|
9
|
+
const rootClasses = classNames({
|
|
10
|
+
[`${className}`]: className,
|
|
11
|
+
});
|
|
12
|
+
const swapSymbolsLabel = React.useMemo(() => {
|
|
13
|
+
if (!currentSwapPair)
|
|
14
|
+
return `Swap`;
|
|
15
|
+
if (swapSide == 'buy')
|
|
16
|
+
return `Swap ${currentSwapPair.quoteToken} / ${currentSwapPair.baseToken}`;
|
|
17
|
+
if (swapSide == 'sell')
|
|
18
|
+
return `Swap ${currentSwapPair.quoteToken} / ${currentSwapPair.baseToken}`;
|
|
19
|
+
}, []);
|
|
20
|
+
return (_jsx(XPRNTransaction, { className: "w-full", actions: swapTransaction, children: swapSymbolsLabel }));
|
|
21
|
+
};
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import classNames from "classnames";
|
|
5
|
+
import { Input } from "../ui/input";
|
|
6
|
+
import { useXPRNSwap } from "./xprn-swap-provider";
|
|
7
|
+
import { toPrecision } from "../../utils";
|
|
8
|
+
export const XPRNSwapField = ({ children, className, type, }) => {
|
|
9
|
+
const { currentSwapPair, swapValues, updateSwapValues, swapVolume } = useXPRNSwap();
|
|
10
|
+
const rootClasses = classNames({
|
|
11
|
+
"swap-field grid grid-cols-[1fr,max-content] items-center gap-2": true,
|
|
12
|
+
[`${className}`]: className,
|
|
13
|
+
});
|
|
14
|
+
const fieldClass = classNames({
|
|
15
|
+
"swap-field_field text-xl font-bold border-0 px-0 placeholder:text-current placeholder:text-opacity-50 focus:border-0 outline-none": true,
|
|
16
|
+
});
|
|
17
|
+
const [value, setValue] = React.useState();
|
|
18
|
+
const [isFocus, setFocus] = React.useState();
|
|
19
|
+
const onSwapValueChange = React.useCallback((value) => {
|
|
20
|
+
setValue(value);
|
|
21
|
+
if (!currentSwapPair)
|
|
22
|
+
return;
|
|
23
|
+
if (type == "base") {
|
|
24
|
+
const prevSwapValue = { ...swapValues, base: parseFloat(value) };
|
|
25
|
+
updateSwapValues(prevSwapValue.base, prevSwapValue.quote, type);
|
|
26
|
+
}
|
|
27
|
+
if (type == "quote") {
|
|
28
|
+
const prevSwapValue = { ...swapValues, quote: parseFloat(value) };
|
|
29
|
+
updateSwapValues(prevSwapValue.base, prevSwapValue.quote, type);
|
|
30
|
+
}
|
|
31
|
+
}, [currentSwapPair, type, swapValues]);
|
|
32
|
+
const onFocus = React.useCallback(() => {
|
|
33
|
+
setFocus(true);
|
|
34
|
+
}, [setFocus]);
|
|
35
|
+
const normalizeValuePrecision = React.useCallback(() => {
|
|
36
|
+
if (!currentSwapPair)
|
|
37
|
+
return;
|
|
38
|
+
if (type == "base")
|
|
39
|
+
setValue(toPrecision(swapValues.base, currentSwapPair.basePrecision));
|
|
40
|
+
if (type == "quote")
|
|
41
|
+
setValue(toPrecision(swapValues.quote, currentSwapPair.quotePrecision));
|
|
42
|
+
setFocus(false);
|
|
43
|
+
}, [swapValues, currentSwapPair, type, setValue, setFocus]);
|
|
44
|
+
const swapSymbol = React.useMemo(() => {
|
|
45
|
+
if (!currentSwapPair)
|
|
46
|
+
return " ";
|
|
47
|
+
if (type == "base")
|
|
48
|
+
return currentSwapPair.baseToken;
|
|
49
|
+
if (type == "quote")
|
|
50
|
+
return currentSwapPair.quoteToken;
|
|
51
|
+
}, [currentSwapPair, type]);
|
|
52
|
+
React.useEffect(() => {
|
|
53
|
+
if (!currentSwapPair)
|
|
54
|
+
return;
|
|
55
|
+
if (isFocus)
|
|
56
|
+
return;
|
|
57
|
+
if (!swapValues)
|
|
58
|
+
return;
|
|
59
|
+
if (type !== swapValues.lastMutated) {
|
|
60
|
+
if (type == 'quote')
|
|
61
|
+
setValue(toPrecision(swapValues.quote, currentSwapPair.quotePrecision));
|
|
62
|
+
if (type == 'base')
|
|
63
|
+
setValue(toPrecision(swapValues.base, currentSwapPair.basePrecision));
|
|
64
|
+
}
|
|
65
|
+
}, [currentSwapPair, type, setValue, swapValues, isFocus, setValue]);
|
|
66
|
+
return (_jsxs("div", { className: rootClasses, children: [_jsx(Input, { className: fieldClass, placeholder: "0.0", onBlur: () => normalizeValuePrecision(), onFocus: () => onFocus(), onChange: e => {
|
|
67
|
+
onSwapValueChange(e.target.value);
|
|
68
|
+
}, value: value }), _jsx("p", { className: "swap-field_dormant text-xl opacity-50 ", children: swapSymbol })] }));
|
|
69
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import classNames from "classnames";
|
|
4
|
+
import { useXPRNSwap } from "./xprn-swap-provider";
|
|
5
|
+
export const XPRNSwapFieldsGroup = ({ children, className, horizontal }) => {
|
|
6
|
+
const { swapSide, config } = useXPRNSwap();
|
|
7
|
+
const rootClasses = classNames({
|
|
8
|
+
"flex gap-4": true,
|
|
9
|
+
"flex-col": !horizontal,
|
|
10
|
+
"flex-row": horizontal,
|
|
11
|
+
"flex-col-reverse": swapSide == "sell" && !horizontal,
|
|
12
|
+
"flex-row-reverse": swapSide == "sell" && horizontal,
|
|
13
|
+
[`${className}`]: className,
|
|
14
|
+
});
|
|
15
|
+
return (_jsx("div", { className: `${rootClasses} `, children: children }));
|
|
16
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useXPRNSwap } from "./xprn-swap-provider";
|
|
4
|
+
import { XPRNSwapField } from "./xprn-swap-field";
|
|
5
|
+
import { XPRNSwapSideButton } from "./xprn-swap-side-button";
|
|
6
|
+
import { XPRNSwapFieldsGroup } from "./xprn-swap-fields-group";
|
|
7
|
+
export const XPRNSwapFields = ({ children, className, }) => {
|
|
8
|
+
const { swapSide, config } = useXPRNSwap();
|
|
9
|
+
return (_jsxs(XPRNSwapFieldsGroup, { children: [_jsxs("div", { className: "flex flex-col", children: [_jsx("p", { children: swapSide == "buy" ? "Sell" : "Buy" }), _jsx("div", { className: "grid grid-cols-[1fr,max-content] items-center gap-2", children: _jsx(XPRNSwapField, { type: "quote" }) }), _jsx("p", { className: "opacity-50", children: "Balance" })] }), config && config.sides && config.sides.length == 1 ? (_jsx("div", { className: "w-full border-t opacity-50 relative" })) : (_jsxs("div", { className: "w-full grid grid-cols-[1fr,min-content,1fr] items-center gap-2", children: [_jsx("div", { className: "w-full border-t opacity-50 relative" }), _jsx(XPRNSwapSideButton, {}), _jsx("div", { className: "w-full border-t opacity-50 relative" })] })), _jsxs("div", { className: "flex flex-col", children: [_jsx("p", { children: swapSide == "sell" ? "Sell" : "Buy" }), _jsx("div", { className: "grid grid-cols-[1fr,max-content] items-center gap-2", children: _jsx(XPRNSwapField, { className: "swap-fields__quote", type: "base" }) }), _jsx("p", { className: "opacity-50", children: "Balance" })] })] }));
|
|
10
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { type XPRNMarketProviderQuoteFilter } from ".";
|
|
3
|
+
type XPRNSwapLayoutProps = React.HTMLAttributes<HTMLDivElement> & {
|
|
4
|
+
filters?: XPRNMarketProviderQuoteFilter;
|
|
5
|
+
};
|
|
6
|
+
export declare const XPRNSwapLayout: React.FunctionComponent<XPRNSwapLayoutProps>;
|
|
7
|
+
export {};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import classNames from "classnames";
|
|
4
|
+
import { XPRNSwapMarketsSelector } from "./xprn-swap-markets-selector";
|
|
5
|
+
import { useXPRNSwap } from "./xprn-swap-provider";
|
|
6
|
+
import { XPRNPairsSelector } from "./xprn-swap-pair-selector";
|
|
7
|
+
import { XPRNSwapFields } from "./xprn-swap-fields";
|
|
8
|
+
import { XPRNSwapButton } from "./xprn-swap-button";
|
|
9
|
+
export const XPRNSwapLayout = ({ children, className, filters, }) => {
|
|
10
|
+
const { swapTransaction, currentMarketPairs, currentSwapPair, marketProviders, swapSide } = useXPRNSwap();
|
|
11
|
+
const rootClasses = classNames({
|
|
12
|
+
"grid grid-col-1 gap-4 rounded-md border border-white p-4": true,
|
|
13
|
+
[`${className}`]: className,
|
|
14
|
+
});
|
|
15
|
+
const headerClass = classNames({
|
|
16
|
+
"grid grid-cols-6 gap-4": marketProviders.length > 1,
|
|
17
|
+
hidden: marketProviders.length <= 1 && currentMarketPairs.length <= 1,
|
|
18
|
+
[`${className}`]: className,
|
|
19
|
+
});
|
|
20
|
+
return (_jsxs("div", { className: `${rootClasses} `, children: [_jsxs("div", { className: headerClass, children: [_jsx(XPRNSwapMarketsSelector, { className: "col-span-2" }), _jsx(XPRNPairsSelector, { className: "col-span-4" })] }), _jsx(XPRNSwapFields, {}), _jsx("div", { children: _jsx(XPRNSwapButton, {}) })] }));
|
|
21
|
+
};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import classNames from "classnames";
|
|
4
|
+
import { Select, SelectItem, SelectContent, SelectTrigger, SelectValue } from "../ui/select";
|
|
5
|
+
import { useXPRNSwap } from ".";
|
|
6
|
+
import { useEffect, useMemo, useState } from "react";
|
|
7
|
+
import { DEFAULT_SWAP_SERVICES } from "./xprn-swap-markets";
|
|
8
|
+
export const XPRNSwapMarketsSelector = ({ children, className }) => {
|
|
9
|
+
const rootClasses = classNames({
|
|
10
|
+
[`${className}`]: className,
|
|
11
|
+
});
|
|
12
|
+
const { marketProviders } = useXPRNSwap();
|
|
13
|
+
const [services, setServices] = useState();
|
|
14
|
+
const defaultServices = useMemo(() => {
|
|
15
|
+
return DEFAULT_SWAP_SERVICES;
|
|
16
|
+
}, []);
|
|
17
|
+
const defaultService = useMemo(() => {
|
|
18
|
+
let foundService = defaultServices.findLast(service => {
|
|
19
|
+
return service.default;
|
|
20
|
+
});
|
|
21
|
+
if (foundService)
|
|
22
|
+
return foundService;
|
|
23
|
+
return defaultServices[0];
|
|
24
|
+
}, [services, defaultServices]);
|
|
25
|
+
useEffect(() => { }, [defaultService]);
|
|
26
|
+
if (marketProviders.length <= 1)
|
|
27
|
+
return;
|
|
28
|
+
return (_jsx("div", { className: `${rootClasses}`, children: _jsxs(Select, { value: defaultService.endpoint, children: [_jsx(SelectTrigger, { children: _jsx(SelectValue, { placeholder: "Theme" }) }), _jsx(SelectContent, { children: defaultServices.map((service, index) => {
|
|
29
|
+
return (_jsx(SelectItem, { value: service.endpoint, children: service.name }, index));
|
|
30
|
+
}) })] }) }));
|
|
31
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { XPRNMarketProvider } from ".";
|
|
2
|
+
export declare enum DEFAULT_SERVICE_NAMES {
|
|
3
|
+
ALCOR = "Alcor",
|
|
4
|
+
METALX = "MetalX",
|
|
5
|
+
XPRSWAP = "XPR Network Swap"
|
|
6
|
+
}
|
|
7
|
+
export declare const DEFAULT_SWAP_SERVICES: XPRNMarketProvider[];
|
|
8
|
+
export declare function getSwapMarkets(filters?: string[]): XPRNMarketProvider[];
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { toPrecision } from "../../utils";
|
|
2
|
+
export var DEFAULT_SERVICE_NAMES;
|
|
3
|
+
(function (DEFAULT_SERVICE_NAMES) {
|
|
4
|
+
DEFAULT_SERVICE_NAMES["ALCOR"] = "Alcor";
|
|
5
|
+
DEFAULT_SERVICE_NAMES["METALX"] = "MetalX";
|
|
6
|
+
DEFAULT_SERVICE_NAMES["XPRSWAP"] = "XPR Network Swap";
|
|
7
|
+
})(DEFAULT_SERVICE_NAMES || (DEFAULT_SERVICE_NAMES = {}));
|
|
8
|
+
export const DEFAULT_SWAP_SERVICES = [
|
|
9
|
+
{
|
|
10
|
+
name: DEFAULT_SERVICE_NAMES.ALCOR,
|
|
11
|
+
endpoint: "https://proton.alcor.exchange/api/markets",
|
|
12
|
+
default: true,
|
|
13
|
+
parse: (result) => {
|
|
14
|
+
return result.map(res => {
|
|
15
|
+
return {
|
|
16
|
+
pair: `${res.quote_token.symbol.name}/${res.base_token.symbol.name}`,
|
|
17
|
+
askName: `${res.quote_token.symbol.name}/${res.base_token.symbol.name}`,
|
|
18
|
+
bidName: `${res.base_token.name}/${res.quote_token.symbol.name}`,
|
|
19
|
+
baseToken: res.base_token.symbol.name,
|
|
20
|
+
basePrecision: res.base_token.symbol.precision,
|
|
21
|
+
baseContract: res.base_token.contract,
|
|
22
|
+
baseTransactionMemo: res.base_token.str,
|
|
23
|
+
quoteToken: res.quote_token.symbol.name,
|
|
24
|
+
quotePrecision: res.quote_token.symbol.precision,
|
|
25
|
+
quoteContract: res.quote_token.contract,
|
|
26
|
+
quoteTransactionMemo: res.quote_token.str,
|
|
27
|
+
ask: res.ask,
|
|
28
|
+
bid: res.bid,
|
|
29
|
+
lastPrice: res.last_price,
|
|
30
|
+
minBuy: res.min_buy,
|
|
31
|
+
minSell: res.min_sell,
|
|
32
|
+
};
|
|
33
|
+
});
|
|
34
|
+
},
|
|
35
|
+
getTransaction(swapPair, volume, price, side, session) {
|
|
36
|
+
if (!session)
|
|
37
|
+
return [];
|
|
38
|
+
const contract = side == 'buy' ? swapPair.baseContract : swapPair.quoteContract;
|
|
39
|
+
const symbol = side == 'buy' ? swapPair.baseToken : swapPair.quoteToken;
|
|
40
|
+
const precision = side == 'buy' ? swapPair.basePrecision : swapPair.quotePrecision;
|
|
41
|
+
const memoBase = side == 'buy' ? swapPair.quoteTransactionMemo : swapPair.baseTransactionMemo;
|
|
42
|
+
return [
|
|
43
|
+
{
|
|
44
|
+
account: contract,
|
|
45
|
+
name: "transfer",
|
|
46
|
+
authorization: [
|
|
47
|
+
{
|
|
48
|
+
actor: session.auth.actor.toString(),
|
|
49
|
+
permission: session.auth.permission.toString(),
|
|
50
|
+
},
|
|
51
|
+
],
|
|
52
|
+
data: {
|
|
53
|
+
from: session.auth.actor.toString(),
|
|
54
|
+
to: "alcor",
|
|
55
|
+
quantity: `${toPrecision(volume, precision, "none", true)} ${symbol}`,
|
|
56
|
+
memo: `${toPrecision(price, precision, "none", true)} ${memoBase}`
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
];
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
// Need info
|
|
63
|
+
// {
|
|
64
|
+
// name: "MetalX",
|
|
65
|
+
// endpoint: "",
|
|
66
|
+
// parse: (result: any[]): XPRNMarketProviderResult[] => {
|
|
67
|
+
// return []
|
|
68
|
+
// },
|
|
69
|
+
// getTransaction(swapPair, volume, side, session) {
|
|
70
|
+
// return []
|
|
71
|
+
// },
|
|
72
|
+
// },
|
|
73
|
+
// {
|
|
74
|
+
// name: "XPR Network",
|
|
75
|
+
// endpoint: "",
|
|
76
|
+
// parse: (result: any[]): XPRNMarketProviderResult[]=>{
|
|
77
|
+
// return []
|
|
78
|
+
// },
|
|
79
|
+
// getTransaction(swapPair, volume, side, session) {
|
|
80
|
+
// return []
|
|
81
|
+
// },
|
|
82
|
+
// }
|
|
83
|
+
];
|
|
84
|
+
export function getSwapMarkets(filters) {
|
|
85
|
+
if (!filters)
|
|
86
|
+
return DEFAULT_SWAP_SERVICES;
|
|
87
|
+
return DEFAULT_SWAP_SERVICES.reduce((prev, current) => {
|
|
88
|
+
const foundInFilter = filters.findIndex(filter => current.name == filter);
|
|
89
|
+
if (foundInFilter >= 0)
|
|
90
|
+
prev.push(current);
|
|
91
|
+
return prev;
|
|
92
|
+
}, []);
|
|
93
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
type XPRNPairsSelectorProps = React.HTMLAttributes<HTMLDivElement> & {
|
|
3
|
+
contentClassName?: string;
|
|
4
|
+
itemsClassName?: string;
|
|
5
|
+
};
|
|
6
|
+
export declare const XPRNPairsSelector: React.FunctionComponent<XPRNPairsSelectorProps>;
|
|
7
|
+
export {};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import classNames from "classnames";
|
|
5
|
+
import { useXPRNSwap } from "./xprn-swap-provider";
|
|
6
|
+
import { Select, SelectItem, SelectContent, SelectTrigger, SelectValue, } from "../ui/select";
|
|
7
|
+
export const XPRNPairsSelector = ({ children, className, contentClassName, itemsClassName }) => {
|
|
8
|
+
const rootClasses = classNames({
|
|
9
|
+
[`${className}`]: className,
|
|
10
|
+
});
|
|
11
|
+
const contentClasses = classNames({
|
|
12
|
+
"bg-white": true,
|
|
13
|
+
[`${contentClassName}`]: className,
|
|
14
|
+
});
|
|
15
|
+
const itemsClasses = classNames({
|
|
16
|
+
"text-black": true,
|
|
17
|
+
[`${itemsClassName}`]: className,
|
|
18
|
+
});
|
|
19
|
+
const { currentMarketPairs, refreshStatus, setCurrentSwapPair, currentSwapPair } = useXPRNSwap();
|
|
20
|
+
const [defaultValue, setDefaultValue] = React.useState();
|
|
21
|
+
const onPairSelected = React.useCallback((pairName) => {
|
|
22
|
+
const foundPair = currentMarketPairs.findLast(pair => {
|
|
23
|
+
return pair.pair == pairName;
|
|
24
|
+
});
|
|
25
|
+
if (foundPair)
|
|
26
|
+
setCurrentSwapPair(foundPair);
|
|
27
|
+
}, [currentMarketPairs]);
|
|
28
|
+
React.useEffect(() => {
|
|
29
|
+
if (currentSwapPair)
|
|
30
|
+
setDefaultValue(currentSwapPair.pair);
|
|
31
|
+
}, [currentSwapPair]);
|
|
32
|
+
if (currentMarketPairs.length <= 1)
|
|
33
|
+
return;
|
|
34
|
+
return (_jsxs(_Fragment, { children: [refreshStatus == "idle" && (_jsx(_Fragment, { children: _jsxs(Select, { value: defaultValue, onValueChange: pair => onPairSelected(pair), children: [_jsx(SelectTrigger, { className: `${rootClasses}`, children: _jsx(SelectValue, { placeholder: "Pairs" }) }), _jsx(SelectContent, { className: contentClasses, children: currentMarketPairs.map((pair, index) => {
|
|
35
|
+
return (_jsx(SelectItem, { value: pair.pair, className: itemsClasses, children: pair.askName }, index));
|
|
36
|
+
}) })] }) })), refreshStatus == "pending" && _jsx(_Fragment, { children: "Loading Pairs" }), refreshStatus == "fail" && _jsx(_Fragment, { children: "Pairs shit" })] }));
|
|
37
|
+
};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import type { XPRNMarketProvider, XPRNMarketProviderQuoteFilter, XPRNMarketProviderResult, XPRNSwapSide, XPRNSwapValues } from ".";
|
|
3
|
+
import type { ServiceStatus } from "../../interfaces/service-status";
|
|
4
|
+
export type XPRNSwapProviderConfig = {
|
|
5
|
+
filters?: XPRNMarketProviderQuoteFilter;
|
|
6
|
+
marketFilters?: string[];
|
|
7
|
+
sides?: XPRNSwapSide[];
|
|
8
|
+
};
|
|
9
|
+
type XPRNProviderProps = {
|
|
10
|
+
children: React.ReactNode | React.ReactNode[];
|
|
11
|
+
config?: XPRNSwapProviderConfig;
|
|
12
|
+
};
|
|
13
|
+
type XPRNSwapProviderContext = {
|
|
14
|
+
marketProviders: XPRNMarketProvider[];
|
|
15
|
+
currentMarketProvider: XPRNMarketProvider | null;
|
|
16
|
+
setCurrentMarketProvider: (marketProvider: XPRNMarketProvider) => void;
|
|
17
|
+
refreshMarketPairs: () => void;
|
|
18
|
+
currentMarketPairs: XPRNMarketProviderResult[];
|
|
19
|
+
refreshStatus: ServiceStatus;
|
|
20
|
+
setCurrentSwapPair: (pair: XPRNMarketProviderResult) => void;
|
|
21
|
+
currentSwapPair: XPRNMarketProviderResult | null;
|
|
22
|
+
currentSwapValues: XPRNSwapValues | null;
|
|
23
|
+
setCurrentSwapValues: (value: XPRNSwapValues) => void;
|
|
24
|
+
swapVolume: number;
|
|
25
|
+
setSwapVolume: (value: number) => void;
|
|
26
|
+
config?: XPRNSwapProviderConfig;
|
|
27
|
+
swapTransaction: any[];
|
|
28
|
+
setSwapSide: (value: XPRNSwapSide) => void;
|
|
29
|
+
swapSide: XPRNSwapSide;
|
|
30
|
+
swapValues: XPRNSwapValues;
|
|
31
|
+
updateSwapValues: (base: number, quote: number, lastMutated: "base" | "quote") => void;
|
|
32
|
+
};
|
|
33
|
+
export declare const XPRNSwapProvider: React.FunctionComponent<XPRNProviderProps>;
|
|
34
|
+
export declare function useXPRNSwap(): XPRNSwapProviderContext;
|
|
35
|
+
export {};
|