console.log('success example function called')}
failFn={() => console.log('fail example function called')}
/>
- {/* Pricing in BCHA */}
+ {/* Pricing in XEC */}
>
);
};
export default Example;
```
### Create a Custom Cashtab Button / Integration
```js
import React from 'react'
import { CashtabBase, formatAmount } from 'cashtab-components'
import styled from 'styled-components'
const CoolButton = styled.button`
background-color: rebeccapurple;
color: lime;
border-radius: 24px;
`
const MyButton extends React.Component {
render() {
// Props from higher order component
const {
handleClick,
to,
step,
price,
currency,
coinType,
coinDecimals,
coinSymbol,
amount,
showQR,
isRepeatable,
repeatTimeout,
watchAddress,
} = this.props;
return (
Donate {price}{currency} to {to}
Satoshis: {formatAmount(amount, coinDecimals)}
Custom looking button with render
)
}
}
// Wrap with CashtabBase higher order component
export default CashtabBase(MyButton);
```
### Control Step from app
When accepting payments, the state of the payment should be handled by the backend of your application. As such, you can pass in `stepControlled` with the values of `fresh`, `pending` or `complete` to indicate which part of the payment the user is on.
## Development with Storybook
To develop additions to this project, run the local storybook development server with
### Setup
```bash
$ npm i
$ npm run storybook
```
Navigate to [http://localhost:9001](http://localhost:9001) to view your stories. They automatically update as you develop ✨.
Storybook will pick up stories from the `*stories.tsx` file in each components folder.
To build a static version of storybook for deployment
```bash
$ npm run build-storybook
Deploy contents of `/storybook-static`
```
diff --git a/web/cashtab-components/src/components/CashtabBadge/CashtabBadge.stories.tsx b/web/cashtab-components/src/components/CashtabBadge/CashtabBadge.stories.tsx
index a31985cc3..3abf2298c 100644
--- a/web/cashtab-components/src/components/CashtabBadge/CashtabBadge.stories.tsx
+++ b/web/cashtab-components/src/components/CashtabBadge/CashtabBadge.stories.tsx
@@ -1,109 +1,109 @@
import { Meta, Story } from '@storybook/react/types-6-0';
import CashtabBadge from './CashtabBadge';
import type { CashtabBadgeProps } from './CashtabBadge';
import { currencyOptions } from '../../utils/currency-helpers';
import Ticker from '../../atoms/Ticker';
// [ SPICE, NAKAMOTO, DOGECASH, BROC ]
const tokenIdOptions = [
'4de69e374a8ed21cbddd47f2338cc0f479dc58daa2bbe11cd604ca488eca0ddf',
'df808a41672a0a0ae6475b44f272a107bc9961b90f29dc918d71301f24fe92fb',
'3916a24a051f8b3833a7fd128be51dd93015555ed9142d6106ec03267f5cdc4c',
'259908ae44f46ef585edef4bcc1e50dc06e4c391ac4be929fae27235b8158cf1',
];
const Template: Story = (args: CashtabBadgeProps) => (
);
export const Standard = Template.bind({});
Standard.args = {
price: 0.05,
currency: 'USD',
to: 'ecash:qrcl220pxeec78vnchwyh6fsdyf60uv9tca7668slm',
};
export const MostProps = Template.bind({});
MostProps.args = {
price: 0.0025,
currency: 'GBP',
to: 'ecash:qrcl220pxeec78vnchwyh6fsdyf60uv9tca7668slm',
isRepeatable: true,
repeatTimeout: 4000,
text: 'My Cash Button',
showAmount: true,
showBorder: true,
showQR: false,
};
export const Minimal = Template.bind({});
Minimal.args = {
amount: 0.01,
to: 'ecash:qrcl220pxeec78vnchwyh6fsdyf60uv9tca7668slm',
showAmount: false,
showQR: true,
};
export const Fiat = Template.bind({});
Fiat.args = {
price: 3.5,
currency: 'CAD',
text: 'Pay with Cashtab',
to: 'ecash:qrcl220pxeec78vnchwyh6fsdyf60uv9tca7668slm',
};
Fiat.storyName = 'price in fiat';
-export const BCHA = Template.bind({});
-BCHA.args = {
+export const XEC = Template.bind({});
+XEC.args = {
coinType: Ticker.coinSymbol,
amount: 0.33,
to: 'ecash:qrcl220pxeec78vnchwyh6fsdyf60uv9tca7668slm',
};
-BCHA.storyName = `price in ${Ticker.coinSymbol}`;
+XEC.storyName = `price in ${Ticker.coinSymbol}`;
export const SLPA = Template.bind({});
SLPA.args = {
coinType: Ticker.tokenTicker,
tokenId: tokenIdOptions[0],
amount: 100,
to: 'etoken:qrcl220pxeec78vnchwyh6fsdyf60uv9tcnqnc3hmv',
showQR: true,
};
SLPA.storyName = `price in ${Ticker.tokenTicker}`;
export const StepControlled = Template.bind({});
StepControlled.args = {
amount: 0.012,
to: 'ecash:qrcl220pxeec78vnchwyh6fsdyf60uv9tca7668slm',
stepControlled: 'fresh',
};
StepControlled.storyName = `Controlled Step`;
export default {
title: 'CashtabBadge',
component: CashtabBadge,
argTypes: {
currency: {
control: {
type: 'select',
options: currencyOptions,
},
},
tokenId: {
control: {
type: 'select',
options: tokenIdOptions,
},
},
stepControlled: {
control: {
type: 'select',
options: ['fresh', 'pending', 'complete'],
},
},
},
} as Meta;
diff --git a/web/cashtab-components/src/components/CashtabButton/CashtabButton.stories.tsx b/web/cashtab-components/src/components/CashtabButton/CashtabButton.stories.tsx
index 4f4e53887..558bdcac7 100644
--- a/web/cashtab-components/src/components/CashtabButton/CashtabButton.stories.tsx
+++ b/web/cashtab-components/src/components/CashtabButton/CashtabButton.stories.tsx
@@ -1,109 +1,109 @@
import { Meta, Story } from '@storybook/react/types-6-0';
import CashtabButton from './CashtabButton';
import type { CashtabButtonProps } from './CashtabButton';
import { currencyOptions } from '../../utils/currency-helpers';
import Ticker from '../../atoms/Ticker';
// [ SPICE, NAKAMOTO, DOGECASH, BROC ]
const tokenIdOptions = [
'4de69e374a8ed21cbddd47f2338cc0f479dc58daa2bbe11cd604ca488eca0ddf',
'df808a41672a0a0ae6475b44f272a107bc9961b90f29dc918d71301f24fe92fb',
'3916a24a051f8b3833a7fd128be51dd93015555ed9142d6106ec03267f5cdc4c',
'259908ae44f46ef585edef4bcc1e50dc06e4c391ac4be929fae27235b8158cf1',
];
const Template: Story = (args: CashtabButtonProps) => (
);
export const Standard = Template.bind({});
Standard.args = {
price: 0.05,
currency: 'USD',
to: 'ecash:qrcl220pxeec78vnchwyh6fsdyf60uv9tca7668slm',
};
export const MostProps = Template.bind({});
MostProps.args = {
price: 0.0025,
currency: 'GBP',
to: 'ecash:qrcl220pxeec78vnchwyh6fsdyf60uv9tca7668slm',
isRepeatable: true,
repeatTimeout: 4000,
text: 'My Cash Button',
showAmount: true,
showBorder: true,
showQR: false,
};
export const Minimal = Template.bind({});
Minimal.args = {
amount: 0.01,
to: 'ecash:qrcl220pxeec78vnchwyh6fsdyf60uv9tca7668slm',
showAmount: false,
showQR: true,
};
export const Fiat = Template.bind({});
Fiat.args = {
price: 3.5,
currency: 'CAD',
text: 'Pay with Cashtab',
to: 'ecash:qrcl220pxeec78vnchwyh6fsdyf60uv9tca7668slm',
};
Fiat.storyName = 'price in fiat';
-export const BCHA = Template.bind({});
-BCHA.args = {
+export const XEC = Template.bind({});
+XEC.args = {
coinType: Ticker.coinSymbol,
amount: 0.33,
to: 'ecash:qrcl220pxeec78vnchwyh6fsdyf60uv9tca7668slm',
};
-BCHA.storyName = `price in ${Ticker.coinSymbol}`;
+XEC.storyName = `price in ${Ticker.coinSymbol}`;
export const SLPA = Template.bind({});
SLPA.args = {
coinType: Ticker.tokenTicker,
tokenId: tokenIdOptions[0],
amount: 100,
to: 'etoken:qrcl220pxeec78vnchwyh6fsdyf60uv9tcnqnc3hmv',
showQR: true,
};
SLPA.storyName = `price in ${Ticker.tokenTicker}`;
export const StepControlled = Template.bind({});
StepControlled.args = {
amount: 0.012,
to: 'ecash:qrcl220pxeec78vnchwyh6fsdyf60uv9tca7668slm',
stepControlled: 'fresh',
};
StepControlled.storyName = `Controlled Step`;
export default {
title: 'CashtabButton',
component: CashtabButton,
argTypes: {
currency: {
control: {
type: 'select',
options: currencyOptions,
},
},
tokenId: {
control: {
type: 'select',
options: tokenIdOptions,
},
},
stepControlled: {
control: {
type: 'select',
options: ['fresh', 'pending', 'complete'],
},
},
},
} as Meta;
diff --git a/web/cashtab-components/src/components/PriceDisplay/README.md b/web/cashtab-components/src/components/PriceDisplay/README.md
index 5cbe80422..f0be03401 100644
--- a/web/cashtab-components/src/components/PriceDisplay/README.md
+++ b/web/cashtab-components/src/components/PriceDisplay/README.md
@@ -1,7 +1,7 @@
# PriceDisplay
-Show a price display item in fiat, BCHA, or SLPA.
+Show a price display item in fiat, XEC, or SLPA.
For open BIP70 invoices, get price and currency info from the invoice.
Used in CashtabBadge and CashtabButton. Useful tool when building custom Cashtab integrations.
diff --git a/web/cashtab-components/src/utils/__tests__/cashtab-helpers.test.ts b/web/cashtab-components/src/utils/__tests__/cashtab-helpers.test.ts
index 947546a23..426cdedbe 100644
--- a/web/cashtab-components/src/utils/__tests__/cashtab-helpers.test.ts
+++ b/web/cashtab-components/src/utils/__tests__/cashtab-helpers.test.ts
@@ -1,33 +1,33 @@
import {
buildPriceEndpoint,
priceToSatoshis,
adjustAmount,
} from '../cashtab-helpers';
describe('Helper functions match expected performance', () => {
it('Component uses expected price endpoint', () => {
expect(buildPriceEndpoint('USD')).toBe(
'https://api.coingecko.com/api/v3/simple/price?ids=bitcoin-cash-abc-2&vs_currencies=USD&include_last_updated_at=true',
);
});
- it('Correctly returns BCHA amount in satoshis given (1) fiat price of BCHA and (2) fiat amount of requested satoshis', () => {
+ it('Correctly returns XEC amount in satoshis given (1) fiat price of XEC and (2) fiat amount of requested satoshis', () => {
expect(priceToSatoshis(20, 10)).toBe(50000000);
});
- it('Converts amount in satoshis as number to amount in BCHA as string', () => {
+ it('Converts amount in satoshis as number to amount in XEC as string', () => {
expect(adjustAmount(50000000, 8, true)).toBe('0.5');
});
- it('Converts amount in BCHA as number to amount in satoshis as string', () => {
+ it('Converts amount in XEC as number to amount in satoshis as string', () => {
expect(adjustAmount(0.5, 8, false)).toBe('50000000');
});
it('Converts amount in base unit of arbitrary decimal places as number to amount in as string', () => {
expect(adjustAmount(50000000, 10, true)).toBe('0.005');
});
it('Converts amount with arbitrary decimal places as number to amount as base unit (no decimal places) as string', () => {
expect(adjustAmount(0.005, 10, false)).toBe('50000000');
});
});