One Hat Cyber Team
Your IP:
216.73.216.102
Server IP:
198.54.114.155
Server:
Linux server71.web-hosting.com 4.18.0-513.18.1.lve.el8.x86_64 #1 SMP Thu Feb 22 12:55:50 UTC 2024 x86_64
Server Software:
LiteSpeed
PHP Version:
5.6.40
Create File
|
Create Folder
Execute
Dir :
~
/
home
/
fluxyjvi
/
www
/
assets
/
images
/
View File Name :
money.tar
src/MoneyFactory.php 0000644 00000074542 15105703712 0010500 0 ustar 00 <?php declare(strict_types=1); namespace Money; use InvalidArgumentException; /** * This is a generated file. Do not edit it manually! * * @method static Money ONEINCH(numeric-string|int $amount) * @method static Money AAVE(numeric-string|int $amount) * @method static Money ACA(numeric-string|int $amount) * @method static Money ACH(numeric-string|int $amount) * @method static Money ACM(numeric-string|int $amount) * @method static Money ADA(numeric-string|int $amount) * @method static Money ADX(numeric-string|int $amount) * @method static Money AED(numeric-string|int $amount) * @method static Money AERGO(numeric-string|int $amount) * @method static Money AFN(numeric-string|int $amount) * @method static Money AGIX(numeric-string|int $amount) * @method static Money AGLD(numeric-string|int $amount) * @method static Money AION(numeric-string|int $amount) * @method static Money AKRO(numeric-string|int $amount) * @method static Money ALCX(numeric-string|int $amount) * @method static Money ALGO(numeric-string|int $amount) * @method static Money ALICE(numeric-string|int $amount) * @method static Money ALL(numeric-string|int $amount) * @method static Money ALPACA(numeric-string|int $amount) * @method static Money ALPHA(numeric-string|int $amount) * @method static Money ALPINE(numeric-string|int $amount) * @method static Money AMB(numeric-string|int $amount) * @method static Money AMD(numeric-string|int $amount) * @method static Money AMP(numeric-string|int $amount) * @method static Money ANC(numeric-string|int $amount) * @method static Money ANG(numeric-string|int $amount) * @method static Money ANKR(numeric-string|int $amount) * @method static Money ANT(numeric-string|int $amount) * @method static Money AOA(numeric-string|int $amount) * @method static Money APE(numeric-string|int $amount) * @method static Money API3(numeric-string|int $amount) * @method static Money APT(numeric-string|int $amount) * @method static Money AR(numeric-string|int $amount) * @method static Money ARDR(numeric-string|int $amount) * @method static Money ARK(numeric-string|int $amount) * @method static Money ARPA(numeric-string|int $amount) * @method static Money ARS(numeric-string|int $amount) * @method static Money ASR(numeric-string|int $amount) * @method static Money AST(numeric-string|int $amount) * @method static Money ASTR(numeric-string|int $amount) * @method static Money ATA(numeric-string|int $amount) * @method static Money ATM(numeric-string|int $amount) * @method static Money ATOM(numeric-string|int $amount) * @method static Money AUCTION(numeric-string|int $amount) * @method static Money AUD(numeric-string|int $amount) * @method static Money AUDIO(numeric-string|int $amount) * @method static Money AUTO(numeric-string|int $amount) * @method static Money AVA(numeric-string|int $amount) * @method static Money AVAX(numeric-string|int $amount) * @method static Money AWG(numeric-string|int $amount) * @method static Money AXS(numeric-string|int $amount) * @method static Money AZN(numeric-string|int $amount) * @method static Money BADGER(numeric-string|int $amount) * @method static Money BAKE(numeric-string|int $amount) * @method static Money BAL(numeric-string|int $amount) * @method static Money BAM(numeric-string|int $amount) * @method static Money BAND(numeric-string|int $amount) * @method static Money BAR(numeric-string|int $amount) * @method static Money BAT(numeric-string|int $amount) * @method static Money BBD(numeric-string|int $amount) * @method static Money BCH(numeric-string|int $amount) * @method static Money BDOT(numeric-string|int $amount) * @method static Money BDT(numeric-string|int $amount) * @method static Money BEAM(numeric-string|int $amount) * @method static Money BEL(numeric-string|int $amount) * @method static Money BETA(numeric-string|int $amount) * @method static Money BETH(numeric-string|int $amount) * @method static Money BGN(numeric-string|int $amount) * @method static Money BHD(numeric-string|int $amount) * @method static Money BICO(numeric-string|int $amount) * @method static Money BIDR(numeric-string|int $amount) * @method static Money BIF(numeric-string|int $amount) * @method static Money BIFI(numeric-string|int $amount) * @method static Money BLZ(numeric-string|int $amount) * @method static Money BMD(numeric-string|int $amount) * @method static Money BNB(numeric-string|int $amount) * @method static Money BND(numeric-string|int $amount) * @method static Money BNT(numeric-string|int $amount) * @method static Money BNX(numeric-string|int $amount) * @method static Money BOB(numeric-string|int $amount) * @method static Money BOND(numeric-string|int $amount) * @method static Money BOV(numeric-string|int $amount) * @method static Money BRL(numeric-string|int $amount) * @method static Money BSD(numeric-string|int $amount) * @method static Money BSW(numeric-string|int $amount) * @method static Money BTC(numeric-string|int $amount) * @method static Money BTCST(numeric-string|int $amount) * @method static Money BTN(numeric-string|int $amount) * @method static Money BTS(numeric-string|int $amount) * @method static Money BTTC(numeric-string|int $amount) * @method static Money BURGER(numeric-string|int $amount) * @method static Money BUSD(numeric-string|int $amount) * @method static Money BWP(numeric-string|int $amount) * @method static Money BYN(numeric-string|int $amount) * @method static Money BZD(numeric-string|int $amount) * @method static Money C98(numeric-string|int $amount) * @method static Money CAD(numeric-string|int $amount) * @method static Money CAKE(numeric-string|int $amount) * @method static Money CDF(numeric-string|int $amount) * @method static Money CELO(numeric-string|int $amount) * @method static Money CELR(numeric-string|int $amount) * @method static Money CFX(numeric-string|int $amount) * @method static Money CHE(numeric-string|int $amount) * @method static Money CHESS(numeric-string|int $amount) * @method static Money CHF(numeric-string|int $amount) * @method static Money CHR(numeric-string|int $amount) * @method static Money CHW(numeric-string|int $amount) * @method static Money CHZ(numeric-string|int $amount) * @method static Money CITY(numeric-string|int $amount) * @method static Money CKB(numeric-string|int $amount) * @method static Money CLF(numeric-string|int $amount) * @method static Money CLP(numeric-string|int $amount) * @method static Money CLV(numeric-string|int $amount) * @method static Money CNY(numeric-string|int $amount) * @method static Money COCOS(numeric-string|int $amount) * @method static Money COMP(numeric-string|int $amount) * @method static Money COP(numeric-string|int $amount) * @method static Money COS(numeric-string|int $amount) * @method static Money COTI(numeric-string|int $amount) * @method static Money COU(numeric-string|int $amount) * @method static Money CRC(numeric-string|int $amount) * @method static Money CREAM(numeric-string|int $amount) * @method static Money CRV(numeric-string|int $amount) * @method static Money CTK(numeric-string|int $amount) * @method static Money CTSI(numeric-string|int $amount) * @method static Money CTXC(numeric-string|int $amount) * @method static Money CUC(numeric-string|int $amount) * @method static Money CUP(numeric-string|int $amount) * @method static Money CVC(numeric-string|int $amount) * @method static Money CVE(numeric-string|int $amount) * @method static Money CVP(numeric-string|int $amount) * @method static Money CVX(numeric-string|int $amount) * @method static Money CZK(numeric-string|int $amount) * @method static Money DAI(numeric-string|int $amount) * @method static Money DAR(numeric-string|int $amount) * @method static Money DASH(numeric-string|int $amount) * @method static Money DATA(numeric-string|int $amount) * @method static Money DCR(numeric-string|int $amount) * @method static Money DEGO(numeric-string|int $amount) * @method static Money DENT(numeric-string|int $amount) * @method static Money DEXE(numeric-string|int $amount) * @method static Money DF(numeric-string|int $amount) * @method static Money DGB(numeric-string|int $amount) * @method static Money DIA(numeric-string|int $amount) * @method static Money DJF(numeric-string|int $amount) * @method static Money DKK(numeric-string|int $amount) * @method static Money DOCK(numeric-string|int $amount) * @method static Money DODO(numeric-string|int $amount) * @method static Money DOGE(numeric-string|int $amount) * @method static Money DOP(numeric-string|int $amount) * @method static Money DOT(numeric-string|int $amount) * @method static Money DREP(numeric-string|int $amount) * @method static Money DUSK(numeric-string|int $amount) * @method static Money DYDX(numeric-string|int $amount) * @method static Money DZD(numeric-string|int $amount) * @method static Money EGLD(numeric-string|int $amount) * @method static Money EGP(numeric-string|int $amount) * @method static Money ELF(numeric-string|int $amount) * @method static Money ENJ(numeric-string|int $amount) * @method static Money ENS(numeric-string|int $amount) * @method static Money EOS(numeric-string|int $amount) * @method static Money EPX(numeric-string|int $amount) * @method static Money ERN(numeric-string|int $amount) * @method static Money ETB(numeric-string|int $amount) * @method static Money ETC(numeric-string|int $amount) * @method static Money ETH(numeric-string|int $amount) * @method static Money EUR(numeric-string|int $amount) * @method static Money FARM(numeric-string|int $amount) * @method static Money FET(numeric-string|int $amount) * @method static Money FIDA(numeric-string|int $amount) * @method static Money FIL(numeric-string|int $amount) * @method static Money FIO(numeric-string|int $amount) * @method static Money FIRO(numeric-string|int $amount) * @method static Money FIS(numeric-string|int $amount) * @method static Money FJD(numeric-string|int $amount) * @method static Money FKP(numeric-string|int $amount) * @method static Money FLM(numeric-string|int $amount) * @method static Money FLOW(numeric-string|int $amount) * @method static Money FLUX(numeric-string|int $amount) * @method static Money FOR(numeric-string|int $amount) * @method static Money FORTH(numeric-string|int $amount) * @method static Money FRONT(numeric-string|int $amount) * @method static Money FTM(numeric-string|int $amount) * @method static Money FTT(numeric-string|int $amount) * @method static Money FUN(numeric-string|int $amount) * @method static Money FXS(numeric-string|int $amount) * @method static Money GAL(numeric-string|int $amount) * @method static Money GALA(numeric-string|int $amount) * @method static Money GAS(numeric-string|int $amount) * @method static Money GBP(numeric-string|int $amount) * @method static Money GEL(numeric-string|int $amount) * @method static Money GHS(numeric-string|int $amount) * @method static Money GHST(numeric-string|int $amount) * @method static Money GIP(numeric-string|int $amount) * @method static Money GLM(numeric-string|int $amount) * @method static Money GLMR(numeric-string|int $amount) * @method static Money GMD(numeric-string|int $amount) * @method static Money GMT(numeric-string|int $amount) * @method static Money GMX(numeric-string|int $amount) * @method static Money GNF(numeric-string|int $amount) * @method static Money GNO(numeric-string|int $amount) * @method static Money GRT(numeric-string|int $amount) * @method static Money GTC(numeric-string|int $amount) * @method static Money GTO(numeric-string|int $amount) * @method static Money GTQ(numeric-string|int $amount) * @method static Money GYD(numeric-string|int $amount) * @method static Money HARD(numeric-string|int $amount) * @method static Money HBAR(numeric-string|int $amount) * @method static Money HFT(numeric-string|int $amount) * @method static Money HIGH(numeric-string|int $amount) * @method static Money HIVE(numeric-string|int $amount) * @method static Money HKD(numeric-string|int $amount) * @method static Money HNL(numeric-string|int $amount) * @method static Money HNT(numeric-string|int $amount) * @method static Money HOOK(numeric-string|int $amount) * @method static Money HOT(numeric-string|int $amount) * @method static Money HTG(numeric-string|int $amount) * @method static Money HUF(numeric-string|int $amount) * @method static Money ICP(numeric-string|int $amount) * @method static Money ICX(numeric-string|int $amount) * @method static Money IDEX(numeric-string|int $amount) * @method static Money IDR(numeric-string|int $amount) * @method static Money IDRT(numeric-string|int $amount) * @method static Money ILS(numeric-string|int $amount) * @method static Money ILV(numeric-string|int $amount) * @method static Money IMX(numeric-string|int $amount) * @method static Money INJ(numeric-string|int $amount) * @method static Money INR(numeric-string|int $amount) * @method static Money IOST(numeric-string|int $amount) * @method static Money IOTA(numeric-string|int $amount) * @method static Money IOTX(numeric-string|int $amount) * @method static Money IQ(numeric-string|int $amount) * @method static Money IQD(numeric-string|int $amount) * @method static Money IRIS(numeric-string|int $amount) * @method static Money IRR(numeric-string|int $amount) * @method static Money ISK(numeric-string|int $amount) * @method static Money JASMY(numeric-string|int $amount) * @method static Money JMD(numeric-string|int $amount) * @method static Money JOD(numeric-string|int $amount) * @method static Money JOE(numeric-string|int $amount) * @method static Money JPY(numeric-string|int $amount) * @method static Money JST(numeric-string|int $amount) * @method static Money JUV(numeric-string|int $amount) * @method static Money KAVA(numeric-string|int $amount) * @method static Money KDA(numeric-string|int $amount) * @method static Money KES(numeric-string|int $amount) * @method static Money KEY(numeric-string|int $amount) * @method static Money KGS(numeric-string|int $amount) * @method static Money KHR(numeric-string|int $amount) * @method static Money KLAY(numeric-string|int $amount) * @method static Money KMD(numeric-string|int $amount) * @method static Money KMF(numeric-string|int $amount) * @method static Money KNC(numeric-string|int $amount) * @method static Money KP3R(numeric-string|int $amount) * @method static Money KPW(numeric-string|int $amount) * @method static Money KRW(numeric-string|int $amount) * @method static Money KSM(numeric-string|int $amount) * @method static Money KWD(numeric-string|int $amount) * @method static Money KYD(numeric-string|int $amount) * @method static Money KZT(numeric-string|int $amount) * @method static Money LAK(numeric-string|int $amount) * @method static Money LAZIO(numeric-string|int $amount) * @method static Money LBP(numeric-string|int $amount) * @method static Money LDO(numeric-string|int $amount) * @method static Money LEVER(numeric-string|int $amount) * @method static Money LINA(numeric-string|int $amount) * @method static Money LINK(numeric-string|int $amount) * @method static Money LIT(numeric-string|int $amount) * @method static Money LKR(numeric-string|int $amount) * @method static Money LOKA(numeric-string|int $amount) * @method static Money LOOM(numeric-string|int $amount) * @method static Money LPT(numeric-string|int $amount) * @method static Money LRC(numeric-string|int $amount) * @method static Money LRD(numeric-string|int $amount) * @method static Money LSK(numeric-string|int $amount) * @method static Money LSL(numeric-string|int $amount) * @method static Money LTC(numeric-string|int $amount) * @method static Money LTO(numeric-string|int $amount) * @method static Money LUNA(numeric-string|int $amount) * @method static Money LUNC(numeric-string|int $amount) * @method static Money LYD(numeric-string|int $amount) * @method static Money MAD(numeric-string|int $amount) * @method static Money MAGIC(numeric-string|int $amount) * @method static Money MANA(numeric-string|int $amount) * @method static Money MASK(numeric-string|int $amount) * @method static Money MATIC(numeric-string|int $amount) * @method static Money MBL(numeric-string|int $amount) * @method static Money MBOX(numeric-string|int $amount) * @method static Money MC(numeric-string|int $amount) * @method static Money MDL(numeric-string|int $amount) * @method static Money MDT(numeric-string|int $amount) * @method static Money MDX(numeric-string|int $amount) * @method static Money MFT(numeric-string|int $amount) * @method static Money MGA(numeric-string|int $amount) * @method static Money MINA(numeric-string|int $amount) * @method static Money MIR(numeric-string|int $amount) * @method static Money MITH(numeric-string|int $amount) * @method static Money MKD(numeric-string|int $amount) * @method static Money MKR(numeric-string|int $amount) * @method static Money MLN(numeric-string|int $amount) * @method static Money MMK(numeric-string|int $amount) * @method static Money MNT(numeric-string|int $amount) * @method static Money MOB(numeric-string|int $amount) * @method static Money MOP(numeric-string|int $amount) * @method static Money MOVR(numeric-string|int $amount) * @method static Money MRU(numeric-string|int $amount) * @method static Money MTL(numeric-string|int $amount) * @method static Money MULTI(numeric-string|int $amount) * @method static Money MUR(numeric-string|int $amount) * @method static Money MVR(numeric-string|int $amount) * @method static Money MWK(numeric-string|int $amount) * @method static Money MXN(numeric-string|int $amount) * @method static Money MXV(numeric-string|int $amount) * @method static Money MYR(numeric-string|int $amount) * @method static Money MZN(numeric-string|int $amount) * @method static Money NAD(numeric-string|int $amount) * @method static Money NEAR(numeric-string|int $amount) * @method static Money NEBL(numeric-string|int $amount) * @method static Money NEO(numeric-string|int $amount) * @method static Money NEXO(numeric-string|int $amount) * @method static Money NGN(numeric-string|int $amount) * @method static Money NIO(numeric-string|int $amount) * @method static Money NKN(numeric-string|int $amount) * @method static Money NMR(numeric-string|int $amount) * @method static Money NOK(numeric-string|int $amount) * @method static Money NPR(numeric-string|int $amount) * @method static Money NULS(numeric-string|int $amount) * @method static Money NZD(numeric-string|int $amount) * @method static Money OAX(numeric-string|int $amount) * @method static Money OCEAN(numeric-string|int $amount) * @method static Money OG(numeric-string|int $amount) * @method static Money OGN(numeric-string|int $amount) * @method static Money OM(numeric-string|int $amount) * @method static Money OMG(numeric-string|int $amount) * @method static Money OMR(numeric-string|int $amount) * @method static Money ONE(numeric-string|int $amount) * @method static Money ONG(numeric-string|int $amount) * @method static Money ONT(numeric-string|int $amount) * @method static Money OOKI(numeric-string|int $amount) * @method static Money OP(numeric-string|int $amount) * @method static Money ORN(numeric-string|int $amount) * @method static Money OSMO(numeric-string|int $amount) * @method static Money OXT(numeric-string|int $amount) * @method static Money PAB(numeric-string|int $amount) * @method static Money PAXG(numeric-string|int $amount) * @method static Money PEN(numeric-string|int $amount) * @method static Money PEOPLE(numeric-string|int $amount) * @method static Money PERL(numeric-string|int $amount) * @method static Money PERP(numeric-string|int $amount) * @method static Money PGK(numeric-string|int $amount) * @method static Money PHA(numeric-string|int $amount) * @method static Money PHB(numeric-string|int $amount) * @method static Money PHP(numeric-string|int $amount) * @method static Money PIVX(numeric-string|int $amount) * @method static Money PKR(numeric-string|int $amount) * @method static Money PLA(numeric-string|int $amount) * @method static Money PLN(numeric-string|int $amount) * @method static Money PNT(numeric-string|int $amount) * @method static Money POLS(numeric-string|int $amount) * @method static Money POLYX(numeric-string|int $amount) * @method static Money POND(numeric-string|int $amount) * @method static Money PORTO(numeric-string|int $amount) * @method static Money POWR(numeric-string|int $amount) * @method static Money PROM(numeric-string|int $amount) * @method static Money PROS(numeric-string|int $amount) * @method static Money PSG(numeric-string|int $amount) * @method static Money PUNDIX(numeric-string|int $amount) * @method static Money PYG(numeric-string|int $amount) * @method static Money PYR(numeric-string|int $amount) * @method static Money QAR(numeric-string|int $amount) * @method static Money QI(numeric-string|int $amount) * @method static Money QKC(numeric-string|int $amount) * @method static Money QLC(numeric-string|int $amount) * @method static Money QNT(numeric-string|int $amount) * @method static Money QTUM(numeric-string|int $amount) * @method static Money QUICK(numeric-string|int $amount) * @method static Money RAD(numeric-string|int $amount) * @method static Money RARE(numeric-string|int $amount) * @method static Money RAY(numeric-string|int $amount) * @method static Money REEF(numeric-string|int $amount) * @method static Money REI(numeric-string|int $amount) * @method static Money REN(numeric-string|int $amount) * @method static Money REP(numeric-string|int $amount) * @method static Money REQ(numeric-string|int $amount) * @method static Money RIF(numeric-string|int $amount) * @method static Money RLC(numeric-string|int $amount) * @method static Money RNDR(numeric-string|int $amount) * @method static Money RON(numeric-string|int $amount) * @method static Money ROSE(numeric-string|int $amount) * @method static Money RSD(numeric-string|int $amount) * @method static Money RSR(numeric-string|int $amount) * @method static Money RUB(numeric-string|int $amount) * @method static Money RUNE(numeric-string|int $amount) * @method static Money RVN(numeric-string|int $amount) * @method static Money RWF(numeric-string|int $amount) * @method static Money SAND(numeric-string|int $amount) * @method static Money SANTOS(numeric-string|int $amount) * @method static Money SAR(numeric-string|int $amount) * @method static Money SBD(numeric-string|int $amount) * @method static Money SC(numeric-string|int $amount) * @method static Money SCR(numeric-string|int $amount) * @method static Money SCRT(numeric-string|int $amount) * @method static Money SDG(numeric-string|int $amount) * @method static Money SEK(numeric-string|int $amount) * @method static Money SFP(numeric-string|int $amount) * @method static Money SGD(numeric-string|int $amount) * @method static Money SHIB(numeric-string|int $amount) * @method static Money SHP(numeric-string|int $amount) * @method static Money SKL(numeric-string|int $amount) * @method static Money SLE(numeric-string|int $amount) * @method static Money SLL(numeric-string|int $amount) * @method static Money SLP(numeric-string|int $amount) * @method static Money SNM(numeric-string|int $amount) * @method static Money SNT(numeric-string|int $amount) * @method static Money SNX(numeric-string|int $amount) * @method static Money SOL(numeric-string|int $amount) * @method static Money SOS(numeric-string|int $amount) * @method static Money SPELL(numeric-string|int $amount) * @method static Money SRD(numeric-string|int $amount) * @method static Money SRM(numeric-string|int $amount) * @method static Money SSP(numeric-string|int $amount) * @method static Money SSV(numeric-string|int $amount) * @method static Money STEEM(numeric-string|int $amount) * @method static Money STG(numeric-string|int $amount) * @method static Money STMX(numeric-string|int $amount) * @method static Money STN(numeric-string|int $amount) * @method static Money STORJ(numeric-string|int $amount) * @method static Money STPT(numeric-string|int $amount) * @method static Money STRAX(numeric-string|int $amount) * @method static Money STX(numeric-string|int $amount) * @method static Money SUN(numeric-string|int $amount) * @method static Money SUPER(numeric-string|int $amount) * @method static Money SUSHI(numeric-string|int $amount) * @method static Money SVC(numeric-string|int $amount) * @method static Money SXP(numeric-string|int $amount) * @method static Money SYP(numeric-string|int $amount) * @method static Money SYS(numeric-string|int $amount) * @method static Money SZL(numeric-string|int $amount) * @method static Money T(numeric-string|int $amount) * @method static Money TFUEL(numeric-string|int $amount) * @method static Money THB(numeric-string|int $amount) * @method static Money THETA(numeric-string|int $amount) * @method static Money TJS(numeric-string|int $amount) * @method static Money TKO(numeric-string|int $amount) * @method static Money TLM(numeric-string|int $amount) * @method static Money TMT(numeric-string|int $amount) * @method static Money TND(numeric-string|int $amount) * @method static Money TOMO(numeric-string|int $amount) * @method static Money TOP(numeric-string|int $amount) * @method static Money TORN(numeric-string|int $amount) * @method static Money TRB(numeric-string|int $amount) * @method static Money TRIBE(numeric-string|int $amount) * @method static Money TROY(numeric-string|int $amount) * @method static Money TRU(numeric-string|int $amount) * @method static Money TRX(numeric-string|int $amount) * @method static Money TRY(numeric-string|int $amount) * @method static Money TTD(numeric-string|int $amount) * @method static Money TVK(numeric-string|int $amount) * @method static Money TWD(numeric-string|int $amount) * @method static Money TWT(numeric-string|int $amount) * @method static Money TZS(numeric-string|int $amount) * @method static Money UAH(numeric-string|int $amount) * @method static Money UFT(numeric-string|int $amount) * @method static Money UGX(numeric-string|int $amount) * @method static Money UMA(numeric-string|int $amount) * @method static Money UNFI(numeric-string|int $amount) * @method static Money UNI(numeric-string|int $amount) * @method static Money USD(numeric-string|int $amount) * @method static Money USDT(numeric-string|int $amount) * @method static Money USN(numeric-string|int $amount) * @method static Money USTC(numeric-string|int $amount) * @method static Money UTK(numeric-string|int $amount) * @method static Money UYI(numeric-string|int $amount) * @method static Money UYU(numeric-string|int $amount) * @method static Money UYW(numeric-string|int $amount) * @method static Money UZS(numeric-string|int $amount) * @method static Money VAI(numeric-string|int $amount) * @method static Money VED(numeric-string|int $amount) * @method static Money VES(numeric-string|int $amount) * @method static Money VET(numeric-string|int $amount) * @method static Money VGX(numeric-string|int $amount) * @method static Money VIB(numeric-string|int $amount) * @method static Money VIDT(numeric-string|int $amount) * @method static Money VITE(numeric-string|int $amount) * @method static Money VND(numeric-string|int $amount) * @method static Money VOXEL(numeric-string|int $amount) * @method static Money VTHO(numeric-string|int $amount) * @method static Money VUV(numeric-string|int $amount) * @method static Money WABI(numeric-string|int $amount) * @method static Money WAN(numeric-string|int $amount) * @method static Money WAVES(numeric-string|int $amount) * @method static Money WAXP(numeric-string|int $amount) * @method static Money WBTC(numeric-string|int $amount) * @method static Money WIN(numeric-string|int $amount) * @method static Money WING(numeric-string|int $amount) * @method static Money WNXM(numeric-string|int $amount) * @method static Money WOO(numeric-string|int $amount) * @method static Money WRX(numeric-string|int $amount) * @method static Money WST(numeric-string|int $amount) * @method static Money WTC(numeric-string|int $amount) * @method static Money XAF(numeric-string|int $amount) * @method static Money XAG(numeric-string|int $amount) * @method static Money XAU(numeric-string|int $amount) * @method static Money XBA(numeric-string|int $amount) * @method static Money XBB(numeric-string|int $amount) * @method static Money XBC(numeric-string|int $amount) * @method static Money XBD(numeric-string|int $amount) * @method static Money XBT(numeric-string|int $amount) * @method static Money XCD(numeric-string|int $amount) * @method static Money XDR(numeric-string|int $amount) * @method static Money XEC(numeric-string|int $amount) * @method static Money XEM(numeric-string|int $amount) * @method static Money XLM(numeric-string|int $amount) * @method static Money XMR(numeric-string|int $amount) * @method static Money XNO(numeric-string|int $amount) * @method static Money XOF(numeric-string|int $amount) * @method static Money XPD(numeric-string|int $amount) * @method static Money XPF(numeric-string|int $amount) * @method static Money XPT(numeric-string|int $amount) * @method static Money XRP(numeric-string|int $amount) * @method static Money XSU(numeric-string|int $amount) * @method static Money XTS(numeric-string|int $amount) * @method static Money XTZ(numeric-string|int $amount) * @method static Money XUA(numeric-string|int $amount) * @method static Money XVG(numeric-string|int $amount) * @method static Money XVS(numeric-string|int $amount) * @method static Money XXX(numeric-string|int $amount) * @method static Money YER(numeric-string|int $amount) * @method static Money YFI(numeric-string|int $amount) * @method static Money YFII(numeric-string|int $amount) * @method static Money YGG(numeric-string|int $amount) * @method static Money ZAR(numeric-string|int $amount) * @method static Money ZEC(numeric-string|int $amount) * @method static Money ZEN(numeric-string|int $amount) * @method static Money ZIL(numeric-string|int $amount) * @method static Money ZMW(numeric-string|int $amount) * @method static Money ZRX(numeric-string|int $amount) * @method static Money ZWL(numeric-string|int $amount) * @psalm-immutable */ trait MoneyFactory { /** * Convenience factory method for a Money object. * * <code> * $fiveDollar = Money::USD(500); * </code> * * @param array $arguments * @psalm-param non-empty-string $method * @psalm-param array{numeric-string|int} $arguments * * @throws InvalidArgumentException If amount is not integer(ish). * * @psalm-pure */ public static function __callStatic(string $method, array $arguments): Money { return new Money($arguments[0], new Currency($method)); } } src/Calculator/GmpCalculator.php 0000644 00000024062 15105703712 0012677 0 ustar 00 <?php declare(strict_types=1); namespace Money\Calculator; use InvalidArgumentException as CoreInvalidArgumentException; use Money\Calculator; use Money\Exception\InvalidArgumentException; use Money\Money; use Money\Number; use function gmp_add; use function gmp_cmp; use function gmp_div_q; use function gmp_div_qr; use function gmp_init; use function gmp_mod; use function gmp_mul; use function gmp_neg; use function gmp_strval; use function gmp_sub; use function ltrim; use function str_pad; use function str_replace; use function strlen; use function substr; use const GMP_ROUND_MINUSINF; use const STR_PAD_LEFT; /** * @psalm-immutable * * Important: the {@see GmpCalculator} is not optimized for decimal operations, as GMP * is designed to operate on large integers. Consider using this only if your * system does not have `ext-bcmath` installed. */ final class GmpCalculator implements Calculator { private const SCALE = 14; /** @psalm-pure */ public static function compare(string $a, string $b): int { $aNum = Number::fromString($a); $bNum = Number::fromString($b); if ($aNum->isDecimal() || $bNum->isDecimal()) { $integersCompared = gmp_cmp($aNum->getIntegerPart(), $bNum->getIntegerPart()); if ($integersCompared !== 0) { return $integersCompared; } $aNumFractional = $aNum->getFractionalPart() === '' ? '0' : $aNum->getFractionalPart(); $bNumFractional = $bNum->getFractionalPart() === '' ? '0' : $bNum->getFractionalPart(); return gmp_cmp($aNumFractional, $bNumFractional); } return gmp_cmp($a, $b); } /** @psalm-pure */ public static function add(string $amount, string $addend): string { return gmp_strval(gmp_add($amount, $addend)); } /** @psalm-pure */ public static function subtract(string $amount, string $subtrahend): string { return gmp_strval(gmp_sub($amount, $subtrahend)); } /** @psalm-pure */ public static function multiply(string $amount, string $multiplier): string { $multiplier = Number::fromString($multiplier); if ($multiplier->isDecimal()) { $decimalPlaces = strlen($multiplier->getFractionalPart()); $multiplierBase = $multiplier->getIntegerPart(); $negativeZero = $multiplierBase === '-0'; if ($negativeZero) { $multiplierBase = '-'; } if ($multiplierBase) { $multiplierBase .= $multiplier->getFractionalPart(); } else { $multiplierBase = ltrim($multiplier->getFractionalPart(), '0'); } $resultBase = gmp_strval(gmp_mul(gmp_init($amount), gmp_init($multiplierBase))); if ($resultBase === '0') { return '0'; } $result = substr($resultBase, $decimalPlaces * -1); $resultLength = strlen($result); if ($decimalPlaces > $resultLength) { /** @psalm-var numeric-string $finalResult */ $finalResult = '0.' . str_pad('', $decimalPlaces - $resultLength, '0') . $result; return $finalResult; } /** @psalm-var numeric-string $finalResult */ $finalResult = substr($resultBase, 0, $decimalPlaces * -1) . '.' . $result; if ($negativeZero) { /** @psalm-var numeric-string $finalResult */ $finalResult = str_replace('-.', '-0.', $finalResult); } return $finalResult; } return gmp_strval(gmp_mul(gmp_init($amount), gmp_init((string) $multiplier))); } /** @psalm-pure */ public static function divide(string $amount, string $divisor): string { if (self::compare($divisor, '0') === 0) { throw InvalidArgumentException::divisionByZero(); } $divisor = Number::fromString($divisor); if ($divisor->isDecimal()) { $decimalPlaces = strlen($divisor->getFractionalPart()); $divisorBase = $divisor->getIntegerPart(); $negativeZero = $divisorBase === '-0'; if ($negativeZero) { $divisorBase = '-'; } if ($divisor->getIntegerPart()) { $divisor = new Number($divisorBase . $divisor->getFractionalPart()); } else { $divisor = new Number(ltrim($divisor->getFractionalPart(), '0')); } $amount = gmp_strval(gmp_mul(gmp_init($amount), gmp_init('1' . str_pad('', $decimalPlaces, '0')))); } [$integer, $remainder] = gmp_div_qr(gmp_init($amount), gmp_init((string) $divisor)); if (gmp_cmp($remainder, '0') === 0) { return gmp_strval($integer); } $divisionOfRemainder = gmp_strval( gmp_div_q( gmp_mul($remainder, gmp_init('1' . str_pad('', self::SCALE, '0'))), gmp_init((string) $divisor), GMP_ROUND_MINUSINF ) ); if ($divisionOfRemainder[0] === '-') { $divisionOfRemainder = substr($divisionOfRemainder, 1); } /** @psalm-var numeric-string $finalResult */ $finalResult = gmp_strval($integer) . '.' . str_pad($divisionOfRemainder, self::SCALE, '0', STR_PAD_LEFT); return $finalResult; } /** @psalm-pure */ public static function ceil(string $number): string { $number = Number::fromString($number); if ($number->isInteger()) { return $number->__toString(); } if ($number->isNegative()) { return self::add($number->getIntegerPart(), '0'); } return self::add($number->getIntegerPart(), '1'); } /** @psalm-pure */ public static function floor(string $number): string { $number = Number::fromString($number); if ($number->isInteger()) { return $number->__toString(); } if ($number->isNegative()) { return self::add($number->getIntegerPart(), '-1'); } return self::add($number->getIntegerPart(), '0'); } /** * @psalm-suppress MoreSpecificReturnType we know that trimming `-` produces a positive numeric-string here * @psalm-suppress LessSpecificReturnStatement we know that trimming `-` produces a positive numeric-string here * @psalm-pure */ public static function absolute(string $number): string { return ltrim($number, '-'); } /** * @psalm-param Money::ROUND_* $roundingMode * * @psalm-return numeric-string * * @psalm-pure */ public static function round(string $number, int $roundingMode): string { $number = Number::fromString($number); if ($number->isInteger()) { return $number->__toString(); } if ($number->isHalf() === false) { return self::roundDigit($number); } if ($roundingMode === Money::ROUND_HALF_UP) { return self::add( $number->getIntegerPart(), $number->getIntegerRoundingMultiplier() ); } if ($roundingMode === Money::ROUND_HALF_DOWN) { return self::add($number->getIntegerPart(), '0'); } if ($roundingMode === Money::ROUND_HALF_EVEN) { if ($number->isCurrentEven()) { return self::add($number->getIntegerPart(), '0'); } return self::add( $number->getIntegerPart(), $number->getIntegerRoundingMultiplier() ); } if ($roundingMode === Money::ROUND_HALF_ODD) { if ($number->isCurrentEven()) { return self::add( $number->getIntegerPart(), $number->getIntegerRoundingMultiplier() ); } return self::add($number->getIntegerPart(), '0'); } if ($roundingMode === Money::ROUND_HALF_POSITIVE_INFINITY) { if ($number->isNegative()) { return self::add( $number->getIntegerPart(), '0' ); } return self::add( $number->getIntegerPart(), $number->getIntegerRoundingMultiplier() ); } if ($roundingMode === Money::ROUND_HALF_NEGATIVE_INFINITY) { if ($number->isNegative()) { return self::add( $number->getIntegerPart(), $number->getIntegerRoundingMultiplier() ); } return self::add( $number->getIntegerPart(), '0' ); } throw new CoreInvalidArgumentException('Unknown rounding mode'); } /** * @psalm-return numeric-string * * @psalm-pure */ private static function roundDigit(Number $number): string { if ($number->isCloserToNext()) { return self::add( $number->getIntegerPart(), $number->getIntegerRoundingMultiplier() ); } return self::add($number->getIntegerPart(), '0'); } /** @psalm-pure */ public static function share(string $amount, string $ratio, string $total): string { return self::floor(self::divide(self::multiply($amount, $ratio), $total)); } /** @psalm-pure */ public static function mod(string $amount, string $divisor): string { if (self::compare($divisor, '0') === 0) { throw InvalidArgumentException::moduloByZero(); } // gmp_mod() only calculates non-negative integers, so we use absolutes $remainder = gmp_mod(self::absolute($amount), self::absolute($divisor)); // If the amount was negative, we negate the result of the modulus operation $amount = Number::fromString($amount); if ($amount->isNegative()) { $remainder = gmp_neg($remainder); } return gmp_strval($remainder); } } src/Calculator/BcMathCalculator.php 0000644 00000013717 15105703712 0013317 0 ustar 00 <?php declare(strict_types=1); namespace Money\Calculator; use InvalidArgumentException as CoreInvalidArgumentException; use Money\Calculator; use Money\Exception\InvalidArgumentException; use Money\Money; use Money\Number; use function bcadd; use function bccomp; use function bcdiv; use function bcmod; use function bcmul; use function bcsub; use function ltrim; use function str_contains; final class BcMathCalculator implements Calculator { private const SCALE = 14; /** @psalm-pure */ public static function compare(string $a, string $b): int { return bccomp($a, $b, self::SCALE); } /** @psalm-pure */ public static function add(string $amount, string $addend): string { $scale = str_contains($amount . $addend, '.') ? self::SCALE : 0; return bcadd($amount, $addend, $scale); } /** @psalm-pure */ public static function subtract(string $amount, string $subtrahend): string { $scale = str_contains($amount . $subtrahend, '.') ? self::SCALE : 0; return bcsub($amount, $subtrahend, $scale); } /** @psalm-pure */ public static function multiply(string $amount, string $multiplier): string { return bcmul($amount, $multiplier, self::SCALE); } /** * @psalm-suppress PossiblyUnusedReturnValue * @psalm-pure */ public static function divide(string $amount, string $divisor): string { if (bccomp($divisor, '0', self::SCALE) === 0) { throw InvalidArgumentException::divisionByZero(); } return bcdiv($amount, $divisor, self::SCALE); } /** @psalm-pure */ public static function ceil(string $number): string { $number = Number::fromString($number); if ($number->isInteger()) { return $number->__toString(); } if ($number->isNegative()) { return bcadd($number->__toString(), '0', 0); } return bcadd($number->__toString(), '1', 0); } /** @psalm-pure */ public static function floor(string $number): string { $number = Number::fromString($number); if ($number->isInteger()) { return $number->__toString(); } if ($number->isNegative()) { return bcadd($number->__toString(), '-1', 0); } return bcadd($number->__toString(), '0', 0); } /** * @psalm-suppress MoreSpecificReturnType we know that trimming `-` produces a positive numeric-string here * @psalm-suppress LessSpecificReturnStatement we know that trimming `-` produces a positive numeric-string here * @psalm-pure */ public static function absolute(string $number): string { return ltrim($number, '-'); } /** * @psalm-param Money::ROUND_* $roundingMode * * @psalm-return numeric-string * * @psalm-pure */ public static function round(string $number, int $roundingMode): string { $number = Number::fromString($number); if ($number->isInteger()) { return $number->__toString(); } if ($number->isHalf() === false) { return self::roundDigit($number); } if ($roundingMode === Money::ROUND_HALF_UP) { return bcadd( $number->__toString(), $number->getIntegerRoundingMultiplier(), 0 ); } if ($roundingMode === Money::ROUND_HALF_DOWN) { return bcadd($number->__toString(), '0', 0); } if ($roundingMode === Money::ROUND_HALF_EVEN) { if ($number->isCurrentEven()) { return bcadd($number->__toString(), '0', 0); } return bcadd( $number->__toString(), $number->getIntegerRoundingMultiplier(), 0 ); } if ($roundingMode === Money::ROUND_HALF_ODD) { if ($number->isCurrentEven()) { return bcadd( $number->__toString(), $number->getIntegerRoundingMultiplier(), 0 ); } return bcadd($number->__toString(), '0', 0); } if ($roundingMode === Money::ROUND_HALF_POSITIVE_INFINITY) { if ($number->isNegative()) { return bcadd($number->__toString(), '0', 0); } return bcadd( $number->__toString(), $number->getIntegerRoundingMultiplier(), 0 ); } if ($roundingMode === Money::ROUND_HALF_NEGATIVE_INFINITY) { if ($number->isNegative()) { return bcadd( $number->__toString(), $number->getIntegerRoundingMultiplier(), 0 ); } return bcadd( $number->__toString(), '0', 0 ); } throw new CoreInvalidArgumentException('Unknown rounding mode'); } /** * @psalm-return numeric-string * * @psalm-pure */ private static function roundDigit(Number $number): string { if ($number->isCloserToNext()) { return bcadd( $number->__toString(), $number->getIntegerRoundingMultiplier(), 0 ); } return bcadd($number->__toString(), '0', 0); } /** @psalm-pure */ public static function share(string $amount, string $ratio, string $total): string { return self::floor(bcdiv(bcmul($amount, $ratio, self::SCALE), $total, self::SCALE)); } /** * @psalm-suppress PossiblyUnusedReturnValue * @psalm-pure */ public static function mod(string $amount, string $divisor): string { if (bccomp($divisor, '0') === 0) { throw InvalidArgumentException::moduloByZero(); } return bcmod($amount, $divisor) ?? '0'; } } src/Exception.php 0000644 00000000222 15105703712 0007777 0 ustar 00 <?php declare(strict_types=1); namespace Money; /** * Common interface for all exceptions thrown by this library. */ interface Exception { } src/Parser/DecimalMoneyParser.php 0000644 00000004716 15105703712 0013034 0 ustar 00 <?php declare(strict_types=1); namespace Money\Parser; use Money\Currencies; use Money\Currency; use Money\Exception\ParserException; use Money\Money; use Money\MoneyParser; use Money\Number; use function ltrim; use function preg_match; use function sprintf; use function str_pad; use function strlen; use function substr; use function trim; /** * Parses a decimal string into a Money object. */ final class DecimalMoneyParser implements MoneyParser { public const DECIMAL_PATTERN = '/^(?P<sign>-)?(?P<digits>\d+)?\.?(?P<fraction>\d+)?$/'; private Currencies $currencies; public function __construct(Currencies $currencies) { $this->currencies = $currencies; } public function parse(string $money, Currency|null $fallbackCurrency = null): Money { if ($fallbackCurrency === null) { throw new ParserException('DecimalMoneyParser cannot parse currency symbols. Use fallbackCurrency argument'); } $decimal = trim($money); if ($decimal === '') { return new Money(0, $fallbackCurrency); } if (! preg_match(self::DECIMAL_PATTERN, $decimal, $matches) || ! isset($matches['digits'])) { throw new ParserException(sprintf('Cannot parse "%s" to Money.', $decimal)); } $negative = isset($matches['sign']) && $matches['sign'] === '-'; $decimal = $matches['digits']; if ($negative) { $decimal = '-' . $decimal; } $subunit = $this->currencies->subunitFor($fallbackCurrency); if (isset($matches['fraction'])) { $fractionDigits = strlen($matches['fraction']); $decimal .= $matches['fraction']; $decimal = Number::roundMoneyValue($decimal, $subunit, $fractionDigits); if ($fractionDigits > $subunit) { $decimal = substr($decimal, 0, $subunit - $fractionDigits); } elseif ($fractionDigits < $subunit) { $decimal .= str_pad('', $subunit - $fractionDigits, '0'); } } else { $decimal .= str_pad('', $subunit, '0'); } if ($negative) { $decimal = '-' . ltrim(substr($decimal, 1), '0'); } else { $decimal = ltrim($decimal, '0'); } if ($decimal === '' || $decimal === '-') { $decimal = '0'; } /** @psalm-var numeric-string $decimal */ return new Money($decimal, $fallbackCurrency); } } src/Parser/AggregateMoneyParser.php 0000644 00000001760 15105703712 0013360 0 ustar 00 <?php declare(strict_types=1); namespace Money\Parser; use Money\Currency; use Money\Exception; use Money\Money; use Money\MoneyParser; use function sprintf; /** * Parses a string into a Money object using other parsers. */ final class AggregateMoneyParser implements MoneyParser { /** * @var MoneyParser[] * @psalm-var non-empty-array<MoneyParser> */ private array $parsers; /** * @param MoneyParser[] $parsers * @psalm-param non-empty-array<MoneyParser> $parsers */ public function __construct(array $parsers) { $this->parsers = $parsers; } public function parse(string $money, Currency|null $fallbackCurrency = null): Money { foreach ($this->parsers as $parser) { try { return $parser->parse($money, $fallbackCurrency); } catch (Exception\ParserException $e) { } } throw new Exception\ParserException(sprintf('Unable to parse %s', $money)); } } src/Parser/IntlLocalizedDecimalParser.php 0000644 00000004555 15105703712 0014503 0 ustar 00 <?php declare(strict_types=1); namespace Money\Parser; use Money\Currencies; use Money\Currency; use Money\Exception\ParserException; use Money\Money; use Money\MoneyParser; use Money\Number; use NumberFormatter; use function ltrim; use function str_pad; use function str_replace; use function strlen; use function strpos; use function substr; /** * Parses a string into a Money object using intl extension. */ final class IntlLocalizedDecimalParser implements MoneyParser { private NumberFormatter $formatter; private Currencies $currencies; public function __construct(NumberFormatter $formatter, Currencies $currencies) { $this->formatter = $formatter; $this->currencies = $currencies; } public function parse(string $money, Currency|null $fallbackCurrency = null): Money { if ($fallbackCurrency === null) { throw new ParserException('IntlLocalizedDecimalParser cannot parse currency symbols. Use forceCurrency argument'); } $decimal = $this->formatter->parse($money); if ($decimal === false) { throw new ParserException('Cannot parse ' . $money . ' to Money. ' . $this->formatter->getErrorMessage()); } $decimal = (string) $decimal; $subunit = $this->currencies->subunitFor($fallbackCurrency); $decimalPosition = strpos($decimal, '.'); if ($decimalPosition !== false) { $decimalLength = strlen($decimal); $fractionDigits = $decimalLength - $decimalPosition - 1; $decimal = str_replace('.', '', $decimal); $decimal = Number::roundMoneyValue($decimal, $subunit, $fractionDigits); if ($fractionDigits > $subunit) { $decimal = substr($decimal, 0, $decimalPosition + $subunit); } elseif ($fractionDigits < $subunit) { $decimal .= str_pad('', $subunit - $fractionDigits, '0'); } } else { $decimal .= str_pad('', $subunit, '0'); } if ($decimal[0] === '-') { $decimal = '-' . ltrim(substr($decimal, 1), '0'); } else { $decimal = ltrim($decimal, '0'); } if ($decimal === '') { $decimal = '0'; } /** @psalm-var numeric-string $decimal */ return new Money($decimal, $fallbackCurrency); } } src/Parser/IntlMoneyParser.php 0000644 00000004744 15105703712 0012405 0 ustar 00 <?php declare(strict_types=1); namespace Money\Parser; use Money\Currencies; use Money\Currency; use Money\Exception\ParserException; use Money\Money; use Money\MoneyParser; use Money\Number; use NumberFormatter; use function assert; use function ltrim; use function str_pad; use function str_replace; use function strlen; use function strpos; use function substr; /** * Parses a string into a Money object using intl extension. */ final class IntlMoneyParser implements MoneyParser { private NumberFormatter $formatter; private Currencies $currencies; public function __construct(NumberFormatter $formatter, Currencies $currencies) { $this->formatter = $formatter; $this->currencies = $currencies; } public function parse(string $money, Currency|null $fallbackCurrency = null): Money { $currency = ''; // phpcs:ignore /** @var string|float|bool|null $decimal */ $decimal = $this->formatter->parseCurrency($money, $currency); if ($decimal === false || $decimal === null) { throw new ParserException('Cannot parse ' . $money . ' to Money. ' . $this->formatter->getErrorMessage()); } if ($fallbackCurrency === null) { assert($currency !== ''); $fallbackCurrency = new Currency($currency); } $decimal = (string) $decimal; $subunit = $this->currencies->subunitFor($fallbackCurrency); $decimalPosition = strpos($decimal, '.'); if ($decimalPosition !== false) { $decimalLength = strlen($decimal); $fractionDigits = $decimalLength - $decimalPosition - 1; $decimal = str_replace('.', '', $decimal); $decimal = Number::roundMoneyValue($decimal, $subunit, $fractionDigits); if ($fractionDigits > $subunit) { $decimal = substr($decimal, 0, $decimalPosition + $subunit); } elseif ($fractionDigits < $subunit) { $decimal .= str_pad('', $subunit - $fractionDigits, '0'); } } else { $decimal .= str_pad('', $subunit, '0'); } if ($decimal[0] === '-') { $decimal = '-' . ltrim(substr($decimal, 1), '0'); } else { $decimal = ltrim($decimal, '0'); } if ($decimal === '') { $decimal = '0'; } /** @psalm-var numeric-string $decimal */ return new Money($decimal, $fallbackCurrency); } } src/Parser/BitcoinMoneyParser.php 0000644 00000003453 15105703712 0013062 0 ustar 00 <?php declare(strict_types=1); namespace Money\Parser; use Money\Currencies\BitcoinCurrencies; use Money\Currency; use Money\Exception\ParserException; use Money\Money; use Money\MoneyParser; use function ltrim; use function rtrim; use function str_pad; use function str_replace; use function strlen; use function strpos; use function substr; /** * Parses Bitcoin currency to Money. */ final class BitcoinMoneyParser implements MoneyParser { private int $fractionDigits; public function __construct(int $fractionDigits) { $this->fractionDigits = $fractionDigits; } public function parse(string $money, Currency|null $fallbackCurrency = null): Money { if (strpos($money, BitcoinCurrencies::SYMBOL) === false) { throw new ParserException('Value cannot be parsed as Bitcoin'); } $currency = $fallbackCurrency ?? new Currency(BitcoinCurrencies::CODE); $decimal = str_replace(BitcoinCurrencies::SYMBOL, '', $money); $decimalSeparator = strpos($decimal, '.'); if ($decimalSeparator !== false) { $decimal = rtrim($decimal, '0'); $lengthDecimal = strlen($decimal); $decimal = str_replace('.', '', $decimal); $decimal .= str_pad('', ($lengthDecimal - $decimalSeparator - $this->fractionDigits - 1) * -1, '0'); } else { $decimal .= str_pad('', $this->fractionDigits, '0'); } if (substr($decimal, 0, 1) === '-') { $decimal = '-' . ltrim(substr($decimal, 1), '0'); } else { $decimal = ltrim($decimal, '0'); } if ($decimal === '') { $decimal = '0'; } /** @psalm-var numeric-string $decimal */ return new Money($decimal, $currency); } } src/Exchange.php 0000644 00000001076 15105703712 0007573 0 ustar 00 <?php declare(strict_types=1); namespace Money; use Money\Exception\UnresolvableCurrencyPairException; /** * Provides a way to get exchange rate from a third-party source and return a currency pair. */ interface Exchange { /** * Returns a currency pair for the passed currencies with the rate coming from a third-party source. * * @throws UnresolvableCurrencyPairException When there is no currency pair (rate) available for the given currencies. */ public function quote(Currency $baseCurrency, Currency $counterCurrency): CurrencyPair; } src/Exception/UnknownCurrencyException.php 0000644 00000000406 15105703712 0015034 0 ustar 00 <?php declare(strict_types=1); namespace Money\Exception; use DomainException; use Money\Exception; /** * Thrown when trying to get ISO currency that does not exists. */ final class UnknownCurrencyException extends DomainException implements Exception { } src/Exception/ParserException.php 0000644 00000000373 15105703712 0013121 0 ustar 00 <?php declare(strict_types=1); namespace Money\Exception; use Money\Exception; use RuntimeException; /** * Thrown when a string cannot be parsed to a Money object. */ final class ParserException extends RuntimeException implements Exception { } src/Exception/UnresolvableCurrencyPairException.php 0000644 00000001422 15105703712 0016651 0 ustar 00 <?php declare(strict_types=1); namespace Money\Exception; use InvalidArgumentException; use Money\Currency; use Money\Exception; use function sprintf; /** * Thrown when there is no currency pair (rate) available for the given currencies. */ final class UnresolvableCurrencyPairException extends InvalidArgumentException implements Exception { /** * Creates an exception from Currency objects. */ public static function createFromCurrencies(Currency $baseCurrency, Currency $counterCurrency): UnresolvableCurrencyPairException { $message = sprintf( 'Cannot resolve a currency pair for currencies: %s/%s', $baseCurrency->getCode(), $counterCurrency->getCode() ); return new self($message); } } src/Exception/FormatterException.php 0000644 00000000403 15105703712 0013622 0 ustar 00 <?php declare(strict_types=1); namespace Money\Exception; use Money\Exception; use RuntimeException; /** * Thrown when a Money object cannot be formatted into a string. */ final class FormatterException extends RuntimeException implements Exception { } src/Exception/InvalidArgumentException.php 0000644 00000001053 15105703713 0014753 0 ustar 00 <?php declare(strict_types=1); namespace Money\Exception; use InvalidArgumentException as CoreInvalidArgumentException; use Money\Exception; final class InvalidArgumentException extends CoreInvalidArgumentException implements Exception { /** @psalm-pure */ public static function divisionByZero(): self { return new self('Cannot compute division with a zero divisor'); } /** @psalm-pure */ public static function moduloByZero(): self { return new self('Cannot compute modulo with a zero divisor'); } } src/Number.php 0000644 00000022126 15105703713 0007301 0 ustar 00 <?php declare(strict_types=1); namespace Money; use InvalidArgumentException; use function abs; use function explode; use function is_int; use function ltrim; use function min; use function rtrim; use function sprintf; use function str_pad; use function strlen; use function substr; /** * Represents a numeric value. * * @internal this is an internal utility of the library, and may vary at any time. It is mostly used to internally validate * that a number is represented at digits, but by improving type system integration, we may be able to completely * get rid of it. * * @psalm-immutable */ final class Number { /** @psalm-var numeric-string */ private string $integerPart; /** @psalm-var numeric-string|'' */ private string $fractionalPart; private const NUMBERS = [0 => 1, 1 => 1, 2 => 1, 3 => 1, 4 => 1, 5 => 1, 6 => 1, 7 => 1, 8 => 1, 9 => 1]; public function __construct(string $integerPart, string $fractionalPart = '') { if ($integerPart === '' && $fractionalPart === '') { throw new InvalidArgumentException('Empty number is invalid'); } $this->integerPart = self::parseIntegerPart($integerPart); $this->fractionalPart = self::parseFractionalPart($fractionalPart); } /** @psalm-pure */ public static function fromString(string $number): self { $portions = explode('.', $number, 2); return new self( $portions[0], rtrim($portions[1] ?? '', '0') ); } /** @psalm-pure */ public static function fromFloat(float $number): self { return self::fromString(sprintf('%.14F', $number)); } /** @psalm-pure */ public static function fromNumber(int|string $number): self { if (is_int($number)) { return new self((string) $number); } return self::fromString($number); } public function isDecimal(): bool { return $this->fractionalPart !== ''; } public function isInteger(): bool { return $this->fractionalPart === ''; } public function isHalf(): bool { return $this->fractionalPart === '5'; } public function isCurrentEven(): bool { $lastIntegerPartNumber = (int) $this->integerPart[strlen($this->integerPart) - 1]; return $lastIntegerPartNumber % 2 === 0; } public function isCloserToNext(): bool { if ($this->fractionalPart === '') { return false; } return $this->fractionalPart[0] >= 5; } /** @psalm-return numeric-string */ public function __toString(): string { if ($this->fractionalPart === '') { return $this->integerPart; } /** @psalm-suppress LessSpecificReturnStatement this operation is guaranteed to pruduce a numeric-string, but inference can't understand it */ return $this->integerPart . '.' . $this->fractionalPart; } public function isNegative(): bool { return $this->integerPart[0] === '-'; } /** @psalm-return numeric-string */ public function getIntegerPart(): string { return $this->integerPart; } /** @psalm-return numeric-string|'' */ public function getFractionalPart(): string { return $this->fractionalPart; } /** @psalm-return numeric-string */ public function getIntegerRoundingMultiplier(): string { if ($this->integerPart[0] === '-') { return '-1'; } return '1'; } public function base10(int $number): self { if ($this->integerPart === '0' && ! $this->fractionalPart) { return $this; } $sign = ''; $integerPart = $this->integerPart; if ($integerPart[0] === '-') { $sign = '-'; $integerPart = substr($integerPart, 1); } if ($number >= 0) { $integerPart = ltrim($integerPart, '0'); $lengthIntegerPart = strlen($integerPart); $integers = $lengthIntegerPart - min($number, $lengthIntegerPart); $zeroPad = $number - min($number, $lengthIntegerPart); return new self( $sign . substr($integerPart, 0, $integers), rtrim(str_pad('', $zeroPad, '0') . substr($integerPart, $integers) . $this->fractionalPart, '0') ); } $number = abs($number); $lengthFractionalPart = strlen($this->fractionalPart); $fractions = $lengthFractionalPart - min($number, $lengthFractionalPart); $zeroPad = $number - min($number, $lengthFractionalPart); return new self( $sign . ltrim($integerPart . substr($this->fractionalPart, 0, $lengthFractionalPart - $fractions) . str_pad('', $zeroPad, '0'), '0'), substr($this->fractionalPart, $lengthFractionalPart - $fractions) ); } /** * @psalm-return numeric-string * * @psalm-pure * * @psalm-suppress MoreSpecificReturnType this operation is guaranteed to pruduce a numeric-string, but inference can't understand it * @psalm-suppress LessSpecificReturnStatement this operation is guaranteed to pruduce a numeric-string, but inference can't understand it */ private static function parseIntegerPart(string $number): string { if ($number === '' || $number === '0') { return '0'; } if ($number === '-') { return '-0'; } // Happy path performance optimization: number can be used as-is if it is within // the platform's integer capabilities. if ($number === (string) (int) $number) { return $number; } $nonZero = false; for ($position = 0, $characters = strlen($number); $position < $characters; ++$position) { $digit = $number[$position]; /** @psalm-suppress InvalidArrayOffset we are, on purpose, checking if the digit is valid against a fixed structure */ if (! isset(self::NUMBERS[$digit]) && ! ($position === 0 && $digit === '-')) { throw new InvalidArgumentException(sprintf('Invalid integer part %1$s. Invalid digit %2$s found', $number, $digit)); } if ($nonZero === false && $digit === '0') { throw new InvalidArgumentException('Leading zeros are not allowed'); } $nonZero = true; } return $number; } /** * @psalm-return numeric-string|'' * * @psalm-pure */ private static function parseFractionalPart(string $number): string { if ($number === '') { return $number; } $intFraction = (int) $number; // Happy path performance optimization: number can be used as-is if it is within // the platform's integer capabilities, and it starts with zeroes only. if ($intFraction > 0 && ltrim($number, '0') === (string) $intFraction) { return $number; } for ($position = 0, $characters = strlen($number); $position < $characters; ++$position) { $digit = $number[$position]; /** @psalm-suppress InvalidArrayOffset we are, on purpose, checking if the digit is valid against a fixed structure */ if (! isset(self::NUMBERS[$digit])) { throw new InvalidArgumentException(sprintf('Invalid fractional part %1$s. Invalid digit %2$s found', $number, $digit)); } } return $number; } /** * @psalm-pure * @psalm-suppress InvalidOperand string and integers get concatenated here - that is by design, as we're computing remainders */ public static function roundMoneyValue(string $moneyValue, int $targetDigits, int $havingDigits): string { $valueLength = strlen($moneyValue); $shouldRound = $targetDigits < $havingDigits && $valueLength - $havingDigits + $targetDigits > 0; if ($shouldRound && $moneyValue[$valueLength - $havingDigits + $targetDigits] >= 5) { $position = $valueLength - $havingDigits + $targetDigits; /** @psalm-var positive-int|0 $addend */ $addend = 1; while ($position > 0) { $newValue = (string) ((int) $moneyValue[$position - 1] + $addend); if ($newValue >= 10) { $moneyValue[$position - 1] = $newValue[1]; /** @psalm-var numeric-string $addend */ $addend = $newValue[0]; --$position; if ($position === 0) { $moneyValue = $addend . $moneyValue; } } else { if ($moneyValue[$position - 1] === '-') { $moneyValue[$position - 1] = $newValue[0]; $moneyValue = '-' . $moneyValue; } else { $moneyValue[$position - 1] = $newValue[0]; } break; } } } return $moneyValue; } } src/Money.php 0000644 00000035423 15105703713 0007144 0 ustar 00 <?php declare(strict_types=1); namespace Money; use InvalidArgumentException; use JsonSerializable; use Money\Calculator\BcMathCalculator; use function array_fill; use function array_keys; use function array_map; use function array_sum; use function count; use function filter_var; use function floor; use function is_int; use function max; use function str_pad; use function strlen; use function substr; use const FILTER_VALIDATE_INT; use const PHP_ROUND_HALF_DOWN; use const PHP_ROUND_HALF_EVEN; use const PHP_ROUND_HALF_ODD; use const PHP_ROUND_HALF_UP; /** * Money Value Object. * * @psalm-immutable */ final class Money implements JsonSerializable { use MoneyFactory; public const ROUND_HALF_UP = PHP_ROUND_HALF_UP; public const ROUND_HALF_DOWN = PHP_ROUND_HALF_DOWN; public const ROUND_HALF_EVEN = PHP_ROUND_HALF_EVEN; public const ROUND_HALF_ODD = PHP_ROUND_HALF_ODD; public const ROUND_UP = 5; public const ROUND_DOWN = 6; public const ROUND_HALF_POSITIVE_INFINITY = 7; public const ROUND_HALF_NEGATIVE_INFINITY = 8; /** * Internal value. * * @psalm-var numeric-string */ private string $amount; private Currency $currency; /** * @var Calculator * @psalm-var class-string<Calculator> */ private static string $calculator = BcMathCalculator::class; /** * @param int|string $amount Amount, expressed in the smallest units of $currency (eg cents) * @psalm-param int|numeric-string $amount * * @throws InvalidArgumentException If amount is not integer(ish). */ public function __construct(int|string $amount, Currency $currency) { $this->currency = $currency; if (filter_var($amount, FILTER_VALIDATE_INT) === false) { $numberFromString = Number::fromString((string) $amount); if (! $numberFromString->isInteger()) { throw new InvalidArgumentException('Amount must be an integer(ish) value'); } $this->amount = $numberFromString->getIntegerPart(); return; } $this->amount = (string) $amount; } /** * Checks whether a Money has the same Currency as this. */ public function isSameCurrency(Money ...$others): bool { foreach ($others as $other) { // Note: non-strict equality is intentional here, since `Currency` is `final` and reliable. if ($this->currency != $other->currency) { return false; } } return true; } /** * Checks whether the value represented by this object equals to the other. */ public function equals(Money $other): bool { // Note: non-strict equality is intentional here, since `Currency` is `final` and reliable. if ($this->currency != $other->currency) { return false; } if ($this->amount === $other->amount) { return true; } // @TODO do we want Money instance to be byte-equivalent when trailing zeroes exist? Very expensive! // Assumption: Money#equals() is called **less** than other number-based comparisons, and probably // only within test suites. Therefore, using complex normalization here is acceptable waste of performance. return $this->compare($other) === 0; } /** * Returns an integer less than, equal to, or greater than zero * if the value of this object is considered to be respectively * less than, equal to, or greater than the other. */ public function compare(Money $other): int { // Note: non-strict equality is intentional here, since `Currency` is `final` and reliable. if ($this->currency != $other->currency) { throw new InvalidArgumentException('Currencies must be identical'); } return self::$calculator::compare($this->amount, $other->amount); } /** * Checks whether the value represented by this object is greater than the other. */ public function greaterThan(Money $other): bool { return $this->compare($other) > 0; } public function greaterThanOrEqual(Money $other): bool { return $this->compare($other) >= 0; } /** * Checks whether the value represented by this object is less than the other. */ public function lessThan(Money $other): bool { return $this->compare($other) < 0; } public function lessThanOrEqual(Money $other): bool { return $this->compare($other) <= 0; } /** * Returns the value represented by this object. * * @psalm-return numeric-string */ public function getAmount(): string { return $this->amount; } /** * Returns the currency of this object. */ public function getCurrency(): Currency { return $this->currency; } /** * Returns a new Money object that represents * the sum of this and an other Money object. * * @param Money[] $addends */ public function add(Money ...$addends): Money { $amount = $this->amount; foreach ($addends as $addend) { // Note: non-strict equality is intentional here, since `Currency` is `final` and reliable. if ($this->currency != $addend->currency) { throw new InvalidArgumentException('Currencies must be identical'); } $amount = self::$calculator::add($amount, $addend->amount); } return new self($amount, $this->currency); } /** * Returns a new Money object that represents * the difference of this and an other Money object. * * @param Money[] $subtrahends * * @psalm-pure */ public function subtract(Money ...$subtrahends): Money { $amount = $this->amount; foreach ($subtrahends as $subtrahend) { // Note: non-strict equality is intentional here, since `Currency` is `final` and reliable. if ($this->currency != $subtrahend->currency) { throw new InvalidArgumentException('Currencies must be identical'); } $amount = self::$calculator::subtract($amount, $subtrahend->amount); } return new self($amount, $this->currency); } /** * Returns a new Money object that represents * the multiplied value by the given factor. * * @psalm-param int|numeric-string $multiplier * @psalm-param self::ROUND_* $roundingMode */ public function multiply(int|string $multiplier, int $roundingMode = self::ROUND_HALF_UP): Money { if (is_int($multiplier)) { $multiplier = (string) $multiplier; } $product = $this->round(self::$calculator::multiply($this->amount, $multiplier), $roundingMode); return new self($product, $this->currency); } /** * Returns a new Money object that represents * the divided value by the given factor. * * @psalm-param int|numeric-string $divisor * @psalm-param self::ROUND_* $roundingMode */ public function divide(int|string $divisor, int $roundingMode = self::ROUND_HALF_UP): Money { if (is_int($divisor)) { $divisor = (string) $divisor; } $quotient = $this->round(self::$calculator::divide($this->amount, $divisor), $roundingMode); return new self($quotient, $this->currency); } /** * Returns a new Money object that represents * the remainder after dividing the value by * the given factor. */ public function mod(Money $divisor): Money { // Note: non-strict equality is intentional here, since `Currency` is `final` and reliable. if ($this->currency != $divisor->currency) { throw new InvalidArgumentException('Currencies must be identical'); } return new self(self::$calculator::mod($this->amount, $divisor->amount), $this->currency); } /** * Allocate the money according to a list of ratios. * * @psalm-param TRatios $ratios * * @return Money[] * @psalm-return ( * TRatios is list * ? non-empty-list<Money> * : non-empty-array<Money> * ) * * @template TRatios as non-empty-array<float|int> */ public function allocate(array $ratios): array { $remainder = $this->amount; $results = []; $total = array_sum($ratios); if ($total <= 0) { throw new InvalidArgumentException('Cannot allocate to none, sum of ratios must be greater than zero'); } foreach ($ratios as $key => $ratio) { if ($ratio < 0) { throw new InvalidArgumentException('Cannot allocate to none, ratio must be zero or positive'); } $share = self::$calculator::share($this->amount, (string) $ratio, (string) $total); $results[$key] = new self($share, $this->currency); $remainder = self::$calculator::subtract($remainder, $share); } if (self::$calculator::compare($remainder, '0') === 0) { return $results; } $amount = $this->amount; $fractions = array_map(static function (float|int $ratio) use ($total, $amount) { $share = (float) $ratio / $total * (float) $amount; return $share - floor($share); }, $ratios); while (self::$calculator::compare($remainder, '0') > 0) { $index = $fractions !== [] ? array_keys($fractions, max($fractions))[0] : 0; $results[$index] = new self(self::$calculator::add($results[$index]->amount, '1'), $results[$index]->currency); $remainder = self::$calculator::subtract($remainder, '1'); unset($fractions[$index]); } return $results; } /** * Allocate the money among N targets. * * @psalm-param positive-int $n * * @return Money[] * @psalm-return non-empty-list<Money> * * @throws InvalidArgumentException If number of targets is not an integer. */ public function allocateTo(int $n): array { return $this->allocate(array_fill(0, $n, 1)); } /** * @psalm-return numeric-string * * @throws InvalidArgumentException if the given $money is zero. */ public function ratioOf(Money $money): string { if ($money->isZero()) { throw new InvalidArgumentException('Cannot calculate a ratio of zero'); } // Note: non-strict equality is intentional here, since `Currency` is `final` and reliable. if ($this->currency != $money->currency) { throw new InvalidArgumentException('Currencies must be identical'); } return self::$calculator::divide($this->amount, $money->amount); } /** * @psalm-param numeric-string $amount * @psalm-param self::ROUND_* $roundingMode * * @psalm-return numeric-string */ private function round(string $amount, int $roundingMode): string { if ($roundingMode === self::ROUND_UP) { return self::$calculator::ceil($amount); } if ($roundingMode === self::ROUND_DOWN) { return self::$calculator::floor($amount); } return self::$calculator::round($amount, $roundingMode); } /** * Round to a specific unit. * * @psalm-param positive-int|0 $unit * @psalm-param self::ROUND_* $roundingMode */ public function roundToUnit(int $unit, int $roundingMode = self::ROUND_HALF_UP): self { if ($unit === 0) { return $this; } $abs = self::$calculator::absolute($this->amount); if (strlen($abs) < $unit) { return new self('0', $this->currency); } /** @psalm-var numeric-string $toBeRounded */ $toBeRounded = substr($this->amount, 0, strlen($this->amount) - $unit) . '.' . substr($this->amount, $unit * -1); $result = $this->round($toBeRounded, $roundingMode); if ($result !== '0') { $result .= str_pad('', $unit, '0'); } /** @psalm-var numeric-string $result */ return new self($result, $this->currency); } public function absolute(): Money { return new self( self::$calculator::absolute($this->amount), $this->currency ); } public function negative(): Money { return (new self(0, $this->currency)) ->subtract($this); } /** * Checks if the value represented by this object is zero. */ public function isZero(): bool { return self::$calculator::compare($this->amount, '0') === 0; } /** * Checks if the value represented by this object is positive. */ public function isPositive(): bool { return self::$calculator::compare($this->amount, '0') > 0; } /** * Checks if the value represented by this object is negative. */ public function isNegative(): bool { return self::$calculator::compare($this->amount, '0') < 0; } /** * {@inheritdoc} * * @psalm-return array{amount: string, currency: string} */ public function jsonSerialize(): array { return [ 'amount' => $this->amount, 'currency' => $this->currency->jsonSerialize(), ]; } /** * @param Money $first * @param Money ...$collection * * @psalm-pure */ public static function min(self $first, self ...$collection): Money { $min = $first; foreach ($collection as $money) { if (! $money->lessThan($min)) { continue; } $min = $money; } return $min; } /** * @param Money $first * @param Money ...$collection * * @psalm-pure */ public static function max(self $first, self ...$collection): Money { $max = $first; foreach ($collection as $money) { if (! $money->greaterThan($max)) { continue; } $max = $money; } return $max; } /** @psalm-pure */ public static function sum(self $first, self ...$collection): Money { return $first->add(...$collection); } /** @psalm-pure */ public static function avg(self $first, self ...$collection): Money { return $first->add(...$collection)->divide((string) (count($collection) + 1)); } /** @psalm-param class-string<Calculator> $calculator */ public static function registerCalculator(string $calculator): void { self::$calculator = $calculator; } /** @psalm-return class-string<Calculator> */ public static function getCalculator(): string { return self::$calculator; } } src/Teller.php 0000644 00000031704 15105703713 0007302 0 ustar 00 <?php declare(strict_types=1); namespace Money; use Money\Currencies\ISOCurrencies; use Money\Formatter\DecimalMoneyFormatter; use Money\Parser\DecimalMoneyParser; use function array_shift; use function is_float; final class Teller { /** * Convenience factory method for a Teller object. * * <code> * $teller = Teller::USD(); * </code> * * @param non-empty-string $method * @param array{0?: int} $arguments * * @return Teller */ public static function __callStatic(string $method, array $arguments): self { $currency = new Currency($method); $currencies = new ISOCurrencies(); $parser = new DecimalMoneyParser($currencies); $formatter = new DecimalMoneyFormatter($currencies); $roundingMode = empty($arguments) ? Money::ROUND_HALF_UP : (int) array_shift($arguments); return new self( $currency, $parser, $formatter, $roundingMode ); } private Currency $currency; private MoneyFormatter $formatter; private MoneyParser $parser; private int $roundingMode = Money::ROUND_HALF_UP; public function __construct( Currency $currency, MoneyParser $parser, MoneyFormatter $formatter, int $roundingMode = Money::ROUND_HALF_UP ) { $this->currency = $currency; $this->parser = $parser; $this->formatter = $formatter; $this->roundingMode = $roundingMode; } /** * Are two monetary amounts equal to each other? * * @param mixed $amount a monetary amount * @param mixed $other another monetary amount */ public function equals(mixed $amount, mixed $other): bool { return $this->convertToMoney($amount)->equals( $this->convertToMoney($other) ); } /** * Returns an integer less than, equal to, or greater than zero if a * monetary amount is respectively less than, equal to, or greater than * another. * * @param mixed $amount a monetary amount * @param mixed $other another monetary amount */ public function compare(mixed $amount, mixed $other): int { return $this->convertToMoney($amount)->compare( $this->convertToMoney($other) ); } /** * Is one monetary amount greater than another? * * @param mixed $amount a monetary amount * @param mixed $other another monetary amount */ public function greaterThan(mixed $amount, mixed $other): bool { return $this->convertToMoney($amount)->greaterThan( $this->convertToMoney($other) ); } /** * Is one monetary amount greater than or equal to another? * * @param mixed $amount a monetary amount * @param mixed $other another monetary amount */ public function greaterThanOrEqual(mixed $amount, mixed $other): bool { return $this->convertToMoney($amount)->greaterThanOrEqual( $this->convertToMoney($other) ); } /** * Is one monetary amount less than another? * * @param mixed $amount a monetary amount * @param mixed $other another monetary amount */ public function lessThan(mixed $amount, mixed $other): bool { return $this->convertToMoney($amount)->lessThan( $this->convertToMoney($other) ); } /** * Is one monetary amount less than or equal to another? * * @param mixed $amount a monetary amount * @param mixed $other another monetary amount */ public function lessThanOrEqual(mixed $amount, mixed $other): bool { return $this->convertToMoney($amount)->lessThanOrEqual( $this->convertToMoney($other) ); } /** * Adds a series of monetary amounts to each other in sequence. * * @param mixed $amount a monetary amount * @param mixed $other another monetary amount * @param mixed[] $others subsequent other monetary amounts * * @return string the calculated monetary amount */ public function add(mixed $amount, mixed $other, mixed ...$others): string { return $this->convertToString( $this->convertToMoney($amount)->add( $this->convertToMoney($other), ...$this->convertToMoneyArray($others) ) ); } /** * Subtracts a series of monetary amounts from each other in sequence. * * @param mixed $amount a monetary amount * @param mixed $other another monetary amount * @param mixed[] $others subsequent monetary amounts */ public function subtract(mixed $amount, mixed $other, mixed ...$others): string { return $this->convertToString( $this->convertToMoney($amount)->subtract( $this->convertToMoney($other), ...$this->convertToMoneyArray($others) ) ); } /** * Multiplies a monetary amount by a factor. * * @param mixed $amount a monetary amount * @param int|float|numeric-string $multiplier the multiplier */ public function multiply(mixed $amount, int|float|string $multiplier): string { $multiplier = is_float($multiplier) ? Number::fromFloat($multiplier) : Number::fromNumber($multiplier); return $this->convertToString( $this->convertToMoney($amount)->multiply( (string) $multiplier, $this->roundingMode ) ); } /** * Divides a monetary amount by a divisor. * * @param mixed $amount a monetary amount * @param int|float|numeric-string $divisor the divisor */ public function divide(mixed $amount, int|float|string $divisor): string { $divisor = is_float($divisor) ? Number::fromFloat($divisor) : Number::fromNumber($divisor); return $this->convertToString( $this->convertToMoney($amount)->divide( (string) $divisor, $this->roundingMode ) ); } /** * Mods a monetary amount by a divisor. * * @param mixed $amount a monetary amount * @param int|float|numeric-string $divisor the divisor */ public function mod(mixed $amount, int|float|string $divisor): string { $divisor = is_float($divisor) ? Number::fromFloat($divisor) : Number::fromNumber($divisor); return $this->convertToString( $this->convertToMoney($amount)->mod( $this->convertToMoney((string) $divisor) ) ); } /** * Allocates a monetary amount according to an array of ratios. * * @param mixed $amount a monetary amount * @param non-empty-array<array-key, float|int> $ratios an array of ratios * * @return string[] the calculated monetary amounts */ public function allocate(mixed $amount, array $ratios): array { return $this->convertToStringArray( $this->convertToMoney($amount)->allocate($ratios) ); } /** * Allocates a monetary amount among N targets. * * @param mixed $amount a monetary amount * @psalm-param positive-int $n the number of targets * * @return string[] the calculated monetary amounts */ public function allocateTo(mixed $amount, int $n): array { return $this->convertToStringArray( $this->convertToMoney($amount)->allocateTo($n) ); } /** * Determines the ratio of one monetary amount to another. * * @param mixed $amount a monetary amount * @param mixed $other another monetary amount */ public function ratioOf(mixed $amount, mixed $other): string { return $this->convertToString( $this->convertToMoney($amount)->ratioOf( $this->convertToMoney($other) ) ); } /** * Returns an absolute monetary amount. * * @param mixed $amount a monetary amount */ public function absolute(mixed $amount): string { return $this->convertToString( $this->convertToMoney($amount)->absolute() ); } /** * Returns the negative of an amount; note that this will convert negative * amounts to positive ones. * * @param mixed $amount a monetary amount */ public function negative(mixed $amount): string { return $this->convertToString( $this->convertToMoney($amount)->negative() ); } /** * Is a monetary amount equal to zero? * * @param mixed $amount a monetary amount */ public function isZero(mixed $amount): bool { return $this->convertToMoney($amount)->isZero(); } /** * Is a monetary amount greater than zero? * * @param mixed $amount a monetary amount */ public function isPositive(mixed $amount): bool { return $this->convertToMoney($amount)->isPositive(); } /** * Is a monetary amount less than zero? * * @param mixed $amount a monetary amount */ public function isNegative(mixed $amount): bool { return $this->convertToMoney($amount)->isNegative(); } /** * Returns the lowest of a series of monetary amounts. * * @param mixed $amount a monetary amount * @param mixed ...$amounts additional monetary amounts */ public function min(mixed $amount, mixed ...$amounts): string { return $this->convertToString( Money::min( $this->convertToMoney($amount), ...$this->convertToMoneyArray($amounts) ) ); } /** * Returns the highest of a series of monetary amounts. * * @param mixed $amount a monetary amount * @param mixed ...$amounts additional monetary amounts */ public function max(mixed $amount, mixed ...$amounts): string { return $this->convertToString( Money::max( $this->convertToMoney($amount), ...$this->convertToMoneyArray($amounts) ) ); } /** * Returns the sum of a series of monetary amounts. * * @param mixed $amount a monetary amount * @param mixed ...$amounts additional monetary amounts */ public function sum(mixed $amount, mixed ...$amounts): string { return $this->convertToString( Money::sum( $this->convertToMoney($amount), ...$this->convertToMoneyArray($amounts) ) ); } /** * Returns the average of a series of monetary amounts. * * @param mixed $amount a monetary amount * @param mixed ...$amounts additional monetary amounts */ public function avg(mixed $amount, mixed ...$amounts): string { return $this->convertToString( Money::avg( $this->convertToMoney($amount), ...$this->convertToMoneyArray($amounts) ) ); } /** * Converts a monetary amount to a Money object. * * @param mixed $amount a monetary amount */ public function convertToMoney(mixed $amount): Money { return $this->parser->parse((string) $amount, $this->currency); } /** * Converts an array of monetary amounts to an array of Money objects. * * @param array<int|string, mixed> $amounts an array of monetary amounts * * @return Money[] */ public function convertToMoneyArray(array $amounts): array { $converted = []; /** @var mixed $amount */ foreach ($amounts as $key => $amount) { $converted[$key] = $this->convertToMoney($amount); } return $converted; } /** * Converts a monetary amount into a Money object, then into a string. * * @param mixed $amount typically a Money object, int, float, or string * representing a monetary amount */ public function convertToString(mixed $amount): string { if ($amount instanceof Money === false) { $amount = $this->convertToMoney($amount); } return $this->formatter->format($amount); } /** * Converts an array of monetary amounts into Money objects, then into * strings. * * @param array<int|string, mixed> $amounts an array of monetary amounts * * @return string[] */ public function convertToStringArray(array $amounts): array { $converted = []; /** @var mixed $amount */ foreach ($amounts as $key => $amount) { $converted[$key] = $this->convertToString($amount); } return $converted; } /** * Returns a "zero" monetary amount. */ public function zero(): string { return '0.00'; } } src/Exchange/FixedExchange.php 0000644 00000002123 15105703713 0012270 0 ustar 00 <?php declare(strict_types=1); namespace Money\Exchange; use Money\Currency; use Money\CurrencyPair; use Money\Exception\UnresolvableCurrencyPairException; use Money\Exchange; /** * Provides a way to get exchange rate from a static list (array). */ final class FixedExchange implements Exchange { /** @psalm-var array<non-empty-string, array<non-empty-string, numeric-string>> */ private array $list; /** @psalm-param array<non-empty-string, array<non-empty-string, numeric-string>> $list */ public function __construct(array $list) { $this->list = $list; } public function quote(Currency $baseCurrency, Currency $counterCurrency): CurrencyPair { if (isset($this->list[$baseCurrency->getCode()][$counterCurrency->getCode()])) { return new CurrencyPair( $baseCurrency, $counterCurrency, $this->list[$baseCurrency->getCode()][$counterCurrency->getCode()] ); } throw UnresolvableCurrencyPairException::createFromCurrencies($baseCurrency, $counterCurrency); } } src/Exchange/IndirectExchangeQueuedItem.php 0000644 00000000613 15105703713 0014764 0 ustar 00 <?php declare(strict_types=1); namespace Money\Exchange; use Money\Currency; /** @internal for sole consumption by {@see IndirectExchange} */ final class IndirectExchangeQueuedItem { public Currency $currency; public bool $discovered = false; public ?self $parent = null; public function __construct(Currency $currency) { $this->currency = $currency; } } src/Exchange/SwapExchange.php 0000644 00000002162 15105703713 0012146 0 ustar 00 <?php declare(strict_types=1); namespace Money\Exchange; use Exchanger\Exception\Exception as ExchangerException; use Money\Currency; use Money\CurrencyPair; use Money\Exception\UnresolvableCurrencyPairException; use Money\Exchange; use Swap\Swap; use function assert; use function is_numeric; use function sprintf; /** * Provides a way to get exchange rate from a third-party source and return a currency pair. */ final class SwapExchange implements Exchange { private Swap $swap; public function __construct(Swap $swap) { $this->swap = $swap; } public function quote(Currency $baseCurrency, Currency $counterCurrency): CurrencyPair { try { $rate = $this->swap->latest($baseCurrency->getCode() . '/' . $counterCurrency->getCode()); } catch (ExchangerException) { throw UnresolvableCurrencyPairException::createFromCurrencies($baseCurrency, $counterCurrency); } $rateValue = sprintf('%.14F', $rate->getValue()); assert(is_numeric($rateValue)); return new CurrencyPair($baseCurrency, $counterCurrency, $rateValue); } } src/Exchange/IndirectExchange.php 0000644 00000010250 15105703713 0012772 0 ustar 00 <?php declare(strict_types=1); namespace Money\Exchange; use Money\Currencies; use Money\Currency; use Money\CurrencyPair; use Money\Exception\UnresolvableCurrencyPairException; use Money\Exchange; use Money\Money; use SplQueue; use function array_reduce; use function array_reverse; /** * Provides a way to get an exchange rate through a minimal set of intermediate conversions. */ final class IndirectExchange implements Exchange { private Currencies $currencies; private Exchange $exchange; public function __construct(Exchange $exchange, Currencies $currencies) { $this->exchange = $exchange; $this->currencies = $currencies; } public function quote(Currency $baseCurrency, Currency $counterCurrency): CurrencyPair { try { return $this->exchange->quote($baseCurrency, $counterCurrency); } catch (UnresolvableCurrencyPairException) { $rate = array_reduce( $this->getConversions($baseCurrency, $counterCurrency), /** * @psalm-param numeric-string $carry * * @psalm-return numeric-string */ static function (string $carry, CurrencyPair $pair) { $calculator = Money::getCalculator(); return $calculator::multiply($carry, $pair->getConversionRatio()); }, '1.0' ); return new CurrencyPair($baseCurrency, $counterCurrency, $rate); } } /** * @return CurrencyPair[] * * @throws UnresolvableCurrencyPairException */ private function getConversions(Currency $baseCurrency, Currency $counterCurrency): array { $startNode = new IndirectExchangeQueuedItem($baseCurrency); $startNode->discovered = true; /** @psalm-var array<non-empty-string, IndirectExchangeQueuedItem> $nodes */ $nodes = [$baseCurrency->getCode() => $startNode]; /** @psam-var SplQueue<IndirectExchangeQueuedItem> $frontier */ $frontier = new SplQueue(); $frontier->enqueue($startNode); while ($frontier->count()) { /** @psalm-var IndirectExchangeQueuedItem $currentNode */ $currentNode = $frontier->dequeue(); $currentCurrency = $currentNode->currency; if ($currentCurrency->equals($counterCurrency)) { return $this->reconstructConversionChain($nodes, $currentNode); } foreach ($this->currencies as $candidateCurrency) { if (! isset($nodes[$candidateCurrency->getCode()])) { $nodes[$candidateCurrency->getCode()] = new IndirectExchangeQueuedItem($candidateCurrency); } $node = $nodes[$candidateCurrency->getCode()]; if ($node->discovered) { continue; } try { // Check if the candidate is a neighbor. This will throw an exception if it isn't. $this->exchange->quote($currentCurrency, $candidateCurrency); $node->discovered = true; $node->parent = $currentNode; $frontier->enqueue($node); } catch (UnresolvableCurrencyPairException $exception) { // Not a neighbor. Move on. } } } throw UnresolvableCurrencyPairException::createFromCurrencies($baseCurrency, $counterCurrency); } /** * @psalm-param array<non-empty-string, IndirectExchangeQueuedItem> $currencies * * @return CurrencyPair[] * @psalm-return list<CurrencyPair> */ private function reconstructConversionChain(array $currencies, IndirectExchangeQueuedItem $goalNode): array { $current = $goalNode; $conversions = []; while ($current->parent) { $previous = $currencies[$current->parent->currency->getCode()]; $conversions[] = $this->exchange->quote($previous->currency, $current->currency); $current = $previous; } return array_reverse($conversions); } } src/Exchange/ReversedCurrenciesExchange.php 0000644 00000002433 15105703713 0015037 0 ustar 00 <?php declare(strict_types=1); namespace Money\Exchange; use Money\Currency; use Money\CurrencyPair; use Money\Exception\UnresolvableCurrencyPairException; use Money\Exchange; use Money\Money; /** * Tries the reverse of the currency pair if one is not available. * * Note: adding nested ReversedCurrenciesExchange could cause a huge performance hit. */ final class ReversedCurrenciesExchange implements Exchange { private Exchange $exchange; public function __construct(Exchange $exchange) { $this->exchange = $exchange; } public function quote(Currency $baseCurrency, Currency $counterCurrency): CurrencyPair { try { return $this->exchange->quote($baseCurrency, $counterCurrency); } catch (UnresolvableCurrencyPairException $exception) { $calculator = Money::getCalculator(); try { $currencyPair = $this->exchange->quote($counterCurrency, $baseCurrency); return new CurrencyPair( $baseCurrency, $counterCurrency, $calculator::divide('1', $currencyPair->getConversionRatio()) ); } catch (UnresolvableCurrencyPairException) { throw $exception; } } } } src/Exchange/ExchangerExchange.php 0000644 00000002624 15105703713 0013143 0 ustar 00 <?php declare(strict_types=1); namespace Money\Exchange; use Exchanger\Contract\ExchangeRateProvider; use Exchanger\CurrencyPair as ExchangerCurrencyPair; use Exchanger\Exception\Exception as ExchangerException; use Exchanger\ExchangeRateQuery; use Money\Currency; use Money\CurrencyPair; use Money\Exception\UnresolvableCurrencyPairException; use Money\Exchange; use function assert; use function is_numeric; use function sprintf; /** * Provides a way to get exchange rate from a third-party source and return a currency pair. */ final class ExchangerExchange implements Exchange { private ExchangeRateProvider $exchanger; public function __construct(ExchangeRateProvider $exchanger) { $this->exchanger = $exchanger; } public function quote(Currency $baseCurrency, Currency $counterCurrency): CurrencyPair { try { $query = new ExchangeRateQuery( new ExchangerCurrencyPair($baseCurrency->getCode(), $counterCurrency->getCode()) ); $rate = $this->exchanger->getExchangeRate($query); } catch (ExchangerException) { throw UnresolvableCurrencyPairException::createFromCurrencies($baseCurrency, $counterCurrency); } $rateValue = sprintf('%.14F', $rate->getValue()); assert(is_numeric($rateValue)); return new CurrencyPair($baseCurrency, $counterCurrency, $rateValue); } } src/Currency.php 0000644 00000002001 15105703713 0007631 0 ustar 00 <?php declare(strict_types=1); namespace Money; use JsonSerializable; use function strtoupper; /** * Currency Value Object. * * Holds Currency specific data. * * @psalm-immutable */ final class Currency implements JsonSerializable { /** * Currency code. * * @psalm-var non-empty-string */ private string $code; /** @psalm-param non-empty-string $code */ public function __construct(string $code) { $this->code = strtoupper($code); } /** * Returns the currency code. * * @psalm-return non-empty-string */ public function getCode(): string { return $this->code; } /** * Checks whether this currency is the same as an other. */ public function equals(Currency $other): bool { return $this->code === $other->code; } public function __toString(): string { return $this->code; } public function jsonSerialize(): string { return $this->code; } } src/Formatter/BitcoinMoneyFormatter.php 0000644 00000004450 15105703713 0014277 0 ustar 00 <?php declare(strict_types=1); namespace Money\Formatter; use Money\Currencies; use Money\Currencies\BitcoinCurrencies; use Money\Exception\FormatterException; use Money\Money; use Money\MoneyFormatter; use Money\Number; use function str_pad; use function strlen; use function strpos; use function substr; /** * Formats Money to Bitcoin currency. */ final class BitcoinMoneyFormatter implements MoneyFormatter { private int $fractionDigits; private Currencies $currencies; public function __construct(int $fractionDigits, Currencies $currencies) { $this->fractionDigits = $fractionDigits; $this->currencies = $currencies; } public function format(Money $money): string { if ($money->getCurrency()->getCode() !== BitcoinCurrencies::CODE) { throw new FormatterException('Bitcoin Formatter can only format Bitcoin currency'); } $valueBase = $money->getAmount(); $negative = false; if ($valueBase[0] === '-') { $negative = true; $valueBase = substr($valueBase, 1); } $subunit = $this->currencies->subunitFor($money->getCurrency()); $valueBase = Number::roundMoneyValue($valueBase, $this->fractionDigits, $subunit); $valueLength = strlen($valueBase); if ($valueLength > $subunit) { $formatted = substr($valueBase, 0, $valueLength - $subunit); if ($subunit) { $formatted .= '.'; $formatted .= substr($valueBase, $valueLength - $subunit); } } else { $formatted = '0.' . str_pad('', $subunit - $valueLength, '0') . $valueBase; } if ($this->fractionDigits === 0) { $formatted = substr($formatted, 0, (int) strpos($formatted, '.')); } elseif ($this->fractionDigits > $subunit) { $formatted .= str_pad('', $this->fractionDigits - $subunit, '0'); } elseif ($this->fractionDigits < $subunit) { $lastDigit = (int) strpos($formatted, '.') + $this->fractionDigits + 1; $formatted = substr($formatted, 0, $lastDigit); } $formatted = BitcoinCurrencies::SYMBOL . $formatted; if ($negative) { $formatted = '-' . $formatted; } return $formatted; } } src/Formatter/DecimalMoneyFormatter.php 0000644 00000002715 15105703713 0014250 0 ustar 00 <?php declare(strict_types=1); namespace Money\Formatter; use Money\Currencies; use Money\Money; use Money\MoneyFormatter; use function assert; use function str_pad; use function strlen; use function substr; /** * Formats a Money object as a decimal string. */ final class DecimalMoneyFormatter implements MoneyFormatter { private Currencies $currencies; public function __construct(Currencies $currencies) { $this->currencies = $currencies; } /** @psalm-return numeric-string */ public function format(Money $money): string { $valueBase = $money->getAmount(); $negative = $valueBase[0] === '-'; if ($negative) { $valueBase = substr($valueBase, 1); } $subunit = $this->currencies->subunitFor($money->getCurrency()); $valueLength = strlen($valueBase); if ($valueLength > $subunit) { $formatted = substr($valueBase, 0, $valueLength - $subunit); $decimalDigits = substr($valueBase, $valueLength - $subunit); if (strlen($decimalDigits) > 0) { $formatted .= '.' . $decimalDigits; } } else { $formatted = '0.' . str_pad('', $subunit - $valueLength, '0') . $valueBase; } if ($negative) { $formatted = '-' . $formatted; } assert($formatted !== ''); /** @psalm-var numeric-string $formatted */ return $formatted; } } src/Formatter/AggregateMoneyFormatter.php 0000644 00000002312 15105703713 0014571 0 ustar 00 <?php declare(strict_types=1); namespace Money\Formatter; use Money\Exception\FormatterException; use Money\Money; use Money\MoneyFormatter; /** * Formats a Money object using other Money formatters. */ final class AggregateMoneyFormatter implements MoneyFormatter { /** * @var MoneyFormatter[] indexed by currency code * @psalm-var non-empty-array<non-empty-string, MoneyFormatter> indexed by currency code */ private array $formatters; /** * @param MoneyFormatter[] $formatters indexed by currency code * @psalm-param non-empty-array<non-empty-string, MoneyFormatter> $formatters indexed by currency code */ public function __construct(array $formatters) { $this->formatters = $formatters; } public function format(Money $money): string { $currencyCode = $money->getCurrency()->getCode(); if (isset($this->formatters[$currencyCode])) { return $this->formatters[$currencyCode]->format($money); } if (isset($this->formatters['*'])) { return $this->formatters['*']->format($money); } throw new FormatterException('No formatter found for currency ' . $currencyCode); } } src/Formatter/IntlLocalizedDecimalFormatter.php 0000644 00000003161 15105703713 0015712 0 ustar 00 <?php declare(strict_types=1); namespace Money\Formatter; use Money\Currencies; use Money\Money; use Money\MoneyFormatter; use NumberFormatter; use function assert; use function is_string; use function str_pad; use function strlen; use function substr; /** * Formats a Money object using intl extension. */ final class IntlLocalizedDecimalFormatter implements MoneyFormatter { private NumberFormatter $formatter; private Currencies $currencies; public function __construct(NumberFormatter $formatter, Currencies $currencies) { $this->formatter = $formatter; $this->currencies = $currencies; } public function format(Money $money): string { $valueBase = $money->getAmount(); $negative = $valueBase[0] === '-'; if ($negative) { $valueBase = substr($valueBase, 1); } $subunit = $this->currencies->subunitFor($money->getCurrency()); $valueLength = strlen($valueBase); if ($valueLength > $subunit) { $formatted = substr($valueBase, 0, $valueLength - $subunit); $decimalDigits = substr($valueBase, $valueLength - $subunit); if (strlen($decimalDigits) > 0) { $formatted .= '.' . $decimalDigits; } } else { $formatted = '0.' . str_pad('', $subunit - $valueLength, '0') . $valueBase; } if ($negative) { $formatted = '-' . $formatted; } $formatted = $this->formatter->format((float) $formatted); assert(is_string($formatted) && $formatted !== ''); return $formatted; } } src/Formatter/IntlMoneyFormatter.php 0000644 00000003137 15105703713 0013617 0 ustar 00 <?php declare(strict_types=1); namespace Money\Formatter; use Money\Currencies; use Money\Money; use Money\MoneyFormatter; use NumberFormatter; use function assert; use function str_pad; use function strlen; use function substr; /** * Formats a Money object using intl extension. */ final class IntlMoneyFormatter implements MoneyFormatter { private NumberFormatter $formatter; private Currencies $currencies; public function __construct(NumberFormatter $formatter, Currencies $currencies) { $this->formatter = $formatter; $this->currencies = $currencies; } public function format(Money $money): string { $valueBase = $money->getAmount(); $negative = $valueBase[0] === '-'; if ($negative) { $valueBase = substr($valueBase, 1); } $subunit = $this->currencies->subunitFor($money->getCurrency()); $valueLength = strlen($valueBase); if ($valueLength > $subunit) { $formatted = substr($valueBase, 0, $valueLength - $subunit); $decimalDigits = substr($valueBase, $valueLength - $subunit); if (strlen($decimalDigits) > 0) { $formatted .= '.' . $decimalDigits; } } else { $formatted = '0.' . str_pad('', $subunit - $valueLength, '0') . $valueBase; } if ($negative) { $formatted = '-' . $formatted; } $formatted = $this->formatter->formatCurrency((float) $formatted, $money->getCurrency()->getCode()); assert($formatted !== ''); return $formatted; } } src/MoneyFormatter.php 0000644 00000000465 15105703713 0011026 0 ustar 00 <?php declare(strict_types=1); namespace Money; /** * Formats Money objects. */ interface MoneyFormatter { /** * Formats a Money object as string. * * @psalm-return non-empty-string * * Exception\FormatterException */ public function format(Money $money): string; } src/PHPUnit/Comparator.php 0000644 00000003673 15105703713 0011455 0 ustar 00 <?php declare(strict_types=1); namespace Money\PHPUnit; use Money\Currencies\AggregateCurrencies; use Money\Currencies\BitcoinCurrencies; use Money\Currencies\ISOCurrencies; use Money\Formatter\IntlMoneyFormatter; use Money\Money; use NumberFormatter; use SebastianBergmann\Comparator\ComparisonFailure; use function assert; /** * The comparator is for comparing Money objects in PHPUnit tests. * * Add this to your bootstrap file: * * \SebastianBergmann\Comparator\Factory::getInstance()->register(new \Money\PHPUnit\Comparator()); * * @internal do not use within your sources: this comparator is only to be used within the test suite of this library * * @psalm-suppress PropertyNotSetInConstructor the parent implementation includes factories that cannot be initialized here */ final class Comparator extends \SebastianBergmann\Comparator\Comparator { private IntlMoneyFormatter $formatter; public function __construct() { parent::__construct(); $currencies = new AggregateCurrencies([ new ISOCurrencies(), new BitcoinCurrencies(), ]); $numberFormatter = new NumberFormatter('en_US', NumberFormatter::CURRENCY); $this->formatter = new IntlMoneyFormatter($numberFormatter, $currencies); } /** {@inheritDoc} */ public function accepts($expected, $actual) { return $expected instanceof Money && $actual instanceof Money; } /** {@inheritDoc} */ public function assertEquals( $expected, $actual, $delta = 0.0, $canonicalize = false, $ignoreCase = false ): void { assert($expected instanceof Money); assert($actual instanceof Money); if (! $expected->equals($actual)) { throw new ComparisonFailure($expected, $actual, $this->formatter->format($expected), $this->formatter->format($actual), false, 'Failed asserting that two Money objects are equal.'); } } } src/CurrencyPair.php 0000644 00000006216 15105703713 0010461 0 ustar 00 <?php declare(strict_types=1); namespace Money; use InvalidArgumentException; use JsonSerializable; use function assert; use function is_numeric; use function preg_match; use function sprintf; /** * Currency Pair holding a base, a counter currency and a conversion ratio. * * @see http://en.wikipedia.org/wiki/Currency_pair */ final class CurrencyPair implements JsonSerializable { /** * Currency to convert from. */ private Currency $baseCurrency; /** * Currency to convert to. */ private Currency $counterCurrency; /** @psalm-var numeric-string */ private string $conversionRatio; /** * @psalm-param numeric-string $conversionRatio */ public function __construct(Currency $baseCurrency, Currency $counterCurrency, string $conversionRatio) { $this->counterCurrency = $counterCurrency; $this->baseCurrency = $baseCurrency; $this->conversionRatio = $conversionRatio; } /** * Creates a new Currency Pair based on "EUR/USD 1.2500" form representation. * * @param string $iso String representation of the form "EUR/USD 1.2500" * * @throws InvalidArgumentException Format of $iso is invalid. */ public static function createFromIso(string $iso): CurrencyPair { $currency = '([A-Z]{2,3})'; $ratio = '([0-9]*\.?[0-9]+)'; // @see http://www.regular-expressions.info/floatingpoint.html $pattern = '#' . $currency . '/' . $currency . ' ' . $ratio . '#'; $matches = []; if (! preg_match($pattern, $iso, $matches)) { throw new InvalidArgumentException(sprintf('Cannot create currency pair from ISO string "%s", format of string is invalid', $iso)); } assert($matches[1] !== ''); assert($matches[2] !== ''); assert(is_numeric($matches[3])); return new self(new Currency($matches[1]), new Currency($matches[2]), $matches[3]); } /** * Returns the counter currency. */ public function getCounterCurrency(): Currency { return $this->counterCurrency; } /** * Returns the base currency. */ public function getBaseCurrency(): Currency { return $this->baseCurrency; } /** * Returns the conversion ratio. * * @psalm-return numeric-string */ public function getConversionRatio(): string { return $this->conversionRatio; } /** * Checks if an other CurrencyPair has the same parameters as this. */ public function equals(CurrencyPair $other): bool { return $this->baseCurrency->equals($other->baseCurrency) && $this->counterCurrency->equals($other->counterCurrency) && $this->conversionRatio === $other->conversionRatio; } /** * {@inheritdoc} * * @psalm-return array{baseCurrency: Currency, counterCurrency: Currency, ratio: numeric-string} */ public function jsonSerialize(): array { return [ 'baseCurrency' => $this->baseCurrency, 'counterCurrency' => $this->counterCurrency, 'ratio' => $this->conversionRatio, ]; } } src/Currencies.php 0000644 00000001327 15105703713 0010153 0 ustar 00 <?php declare(strict_types=1); namespace Money; use IteratorAggregate; use Money\Exception\UnknownCurrencyException; use Traversable; /** * Implement this to provide a list of currencies. */ interface Currencies extends IteratorAggregate { /** * Checks whether a currency is available in the current context. */ public function contains(Currency $currency): bool; /** * Returns the subunit for a currency. * * @throws UnknownCurrencyException If currency is not available in the current context. */ public function subunitFor(Currency $currency): int; /** * @psalm-return Traversable<int|string, Currency> */ public function getIterator(): Traversable; } src/Converter.php 0000644 00000004565 15105703713 0010027 0 ustar 00 <?php declare(strict_types=1); namespace Money; use InvalidArgumentException; use function sprintf; /** * Provides a way to convert Money to Money in another Currency using an exchange rate. */ final class Converter { private Currencies $currencies; private Exchange $exchange; public function __construct(Currencies $currencies, Exchange $exchange) { $this->currencies = $currencies; $this->exchange = $exchange; } public function convert(Money $money, Currency $counterCurrency, int $roundingMode = Money::ROUND_HALF_UP): Money { return $this->convertAgainstCurrencyPair( $money, $this->exchange->quote( $money->getCurrency(), $counterCurrency ), $roundingMode ); } /** @return array{0: Money, 1: CurrencyPair} */ public function convertAndReturnWithCurrencyPair(Money $money, Currency $counterCurrency, int $roundingMode = Money::ROUND_HALF_UP): array { $pair = $this->exchange->quote( $money->getCurrency(), $counterCurrency ); return [$this->convertAgainstCurrencyPair($money, $pair, $roundingMode), $pair]; } public function convertAgainstCurrencyPair(Money $money, CurrencyPair $currencyPair, int $roundingMode = Money::ROUND_HALF_UP): Money { if (! $money->getCurrency()->equals($currencyPair->getBaseCurrency())) { throw new InvalidArgumentException( sprintf( 'Expecting to convert against base currency %s, but got %s instead', $money->getCurrency()->getCode(), $currencyPair->getBaseCurrency()->getCode() ) ); } $ratio = $currencyPair->getConversionRatio(); $baseCurrencySubunit = $this->currencies->subunitFor($currencyPair->getBaseCurrency()); $counterCurrencySubunit = $this->currencies->subunitFor($currencyPair->getCounterCurrency()); $subunitDifference = $baseCurrencySubunit - $counterCurrencySubunit; $ratio = Number::fromString($ratio) ->base10($subunitDifference) ->__toString(); $counterValue = $money->multiply($ratio, $roundingMode); return new Money($counterValue->getAmount(), $currencyPair->getCounterCurrency()); } } src/Currencies/CachedCurrencies.php 0000644 00000004304 15105703713 0013343 0 ustar 00 <?php declare(strict_types=1); namespace Money\Currencies; use ArrayIterator; use Cache\TagInterop\TaggableCacheItemInterface; use CallbackFilterIterator; use Money\Currencies; use Money\Currency; use Psr\Cache\CacheItemPoolInterface; use Traversable; use function iterator_to_array; /** * Cache the result of currency checking. */ final class CachedCurrencies implements Currencies { private Currencies $currencies; private CacheItemPoolInterface $pool; public function __construct(Currencies $currencies, CacheItemPoolInterface $pool) { $this->currencies = $currencies; $this->pool = $pool; } public function contains(Currency $currency): bool { $item = $this->pool->getItem('currency|availability|' . $currency->getCode()); if ($item->isHit() === false) { $item->set($this->currencies->contains($currency)); if ($item instanceof TaggableCacheItemInterface) { $item->setTags(['currency.availability']); } $this->pool->save($item); } return (bool) $item->get(); } public function subunitFor(Currency $currency): int { $item = $this->pool->getItem('currency|subunit|' . $currency->getCode()); if ($item->isHit() === false) { $item->set($this->currencies->subunitFor($currency)); if ($item instanceof TaggableCacheItemInterface) { $item->setTags(['currency.subunit']); } $this->pool->save($item); } return (int) $item->get(); } /** {@inheritDoc} */ public function getIterator(): Traversable { return new CallbackFilterIterator( new ArrayIterator(iterator_to_array($this->currencies->getIterator())), function (Currency $currency): bool { $item = $this->pool->getItem('currency|availability|' . $currency->getCode()); $item->set(true); if ($item instanceof TaggableCacheItemInterface) { $item->setTags(['currency.availability']); } $this->pool->save($item); return true; } ); } } src/Currencies/CurrencyList.php 0000644 00000002571 15105703713 0012603 0 ustar 00 <?php declare(strict_types=1); namespace Money\Currencies; use ArrayIterator; use Money\Currencies; use Money\Currency; use Money\Exception\UnknownCurrencyException; use Traversable; use function array_keys; use function array_map; /** * A list of custom currencies. */ final class CurrencyList implements Currencies { /** * Map of currencies and their sub-units indexed by code. * * @psalm-var array<non-empty-string, int> */ private array $currencies; /** @psalm-param array<non-empty-string, positive-int|0> $currencies */ public function __construct(array $currencies) { $this->currencies = $currencies; } public function contains(Currency $currency): bool { return isset($this->currencies[$currency->getCode()]); } public function subunitFor(Currency $currency): int { if (! $this->contains($currency)) { throw new UnknownCurrencyException('Cannot find currency ' . $currency->getCode()); } return $this->currencies[$currency->getCode()]; } /** {@inheritDoc} */ public function getIterator(): Traversable { return new ArrayIterator( array_map( static function ($code) { return new Currency($code); }, array_keys($this->currencies) ) ); } } src/Currencies/BitcoinCurrencies.php 0000644 00000001544 15105703713 0013566 0 ustar 00 <?php declare(strict_types=1); namespace Money\Currencies; use ArrayIterator; use Money\Currencies; use Money\Currency; use Money\Exception\UnknownCurrencyException; use Traversable; final class BitcoinCurrencies implements Currencies { public const CODE = 'XBT'; public const SYMBOL = "\xC9\x83"; public function contains(Currency $currency): bool { return $currency->getCode() === self::CODE; } public function subunitFor(Currency $currency): int { if ($currency->getCode() !== self::CODE) { throw new UnknownCurrencyException($currency->getCode() . ' is not bitcoin and is not supported by this currency repository'); } return 8; } /** {@inheritDoc} */ public function getIterator(): Traversable { return new ArrayIterator([new Currency(self::CODE)]); } } src/Currencies/AggregateCurrencies.php 0000644 00000003134 15105703713 0014062 0 ustar 00 <?php declare(strict_types=1); namespace Money\Currencies; use AppendIterator; use Money\Currencies; use Money\Currency; use Money\Exception\UnknownCurrencyException; use Traversable; /** * Aggregates several currency repositories. */ final class AggregateCurrencies implements Currencies { /** @var Currencies[] */ private array $currencies; /** * @param Currencies[] $currencies */ public function __construct(array $currencies) { $this->currencies = $currencies; } public function contains(Currency $currency): bool { foreach ($this->currencies as $currencies) { if ($currencies->contains($currency)) { return true; } } return false; } public function subunitFor(Currency $currency): int { foreach ($this->currencies as $currencies) { if ($currencies->contains($currency)) { return $currencies->subunitFor($currency); } } throw new UnknownCurrencyException('Cannot find currency ' . $currency->getCode()); } /** {@inheritDoc} */ public function getIterator(): Traversable { /** @psalm-var AppendIterator&Traversable<int|string, Currency> $iterator */ $iterator = new AppendIterator(); foreach ($this->currencies as $currencies) { $currencyIterator = $currencies->getIterator(); /** @psalm-var AppendIterator&Traversable<int|string, Currency> $currencyIterator */ $iterator->append($currencyIterator); } return $iterator; } } src/Currencies/ISOCurrencies.php 0000644 00000006171 15105703713 0012632 0 ustar 00 <?php declare(strict_types=1); namespace Money\Currencies; use ArrayIterator; use Money\Currencies; use Money\Currency; use Money\Exception\UnknownCurrencyException; use RuntimeException; use Traversable; use function array_keys; use function array_map; use function is_file; /** * List of supported ISO 4217 currency codes and names. */ final class ISOCurrencies implements Currencies { /** * Map of known currencies indexed by code. * * @psalm-var non-empty-array<non-empty-string, array{ * alphabeticCode: non-empty-string, * currency: non-empty-string, * minorUnit: positive-int|0, * numericCode: positive-int * }>|null */ private static ?array $currencies = null; public function contains(Currency $currency): bool { return isset($this->getCurrencies()[$currency->getCode()]); } public function subunitFor(Currency $currency): int { if (! $this->contains($currency)) { throw new UnknownCurrencyException('Cannot find ISO currency ' . $currency->getCode()); } return $this->getCurrencies()[$currency->getCode()]['minorUnit']; } /** * Returns the numeric code for a currency. * * @throws UnknownCurrencyException If currency is not available in the current context. */ public function numericCodeFor(Currency $currency): int { if (! $this->contains($currency)) { throw new UnknownCurrencyException('Cannot find ISO currency ' . $currency->getCode()); } return $this->getCurrencies()[$currency->getCode()]['numericCode']; } /** * @psalm-return Traversable<int, Currency> */ public function getIterator(): Traversable { return new ArrayIterator( array_map( static function ($code) { return new Currency($code); }, array_keys($this->getCurrencies()) ) ); } /** * Returns a map of known currencies indexed by code. * * @psalm-return non-empty-array<non-empty-string, array{ * alphabeticCode: non-empty-string, * currency: non-empty-string, * minorUnit: positive-int|0, * numericCode: positive-int * }> */ private function getCurrencies(): array { if (self::$currencies === null) { self::$currencies = $this->loadCurrencies(); } return self::$currencies; } /** * @psalm-return non-empty-array<non-empty-string, array{ * alphabeticCode: non-empty-string, * currency: non-empty-string, * minorUnit: positive-int|0, * numericCode: positive-int * }> * * @psalm-suppress MoreSpecificReturnType do not specify all keys and values */ private function loadCurrencies(): array { $file = __DIR__ . '/../../resources/currency.php'; if (is_file($file)) { /** @psalm-suppress LessSpecificReturnStatement */ return require $file; } throw new RuntimeException('Failed to load currency ISO codes.'); } } src/Currencies/CryptoCurrencies.php 0000644 00000004702 15105703713 0013456 0 ustar 00 <?php declare(strict_types=1); namespace Money\Currencies; use ArrayIterator; use Money\Currencies; use Money\Currency; use Money\Exception\UnknownCurrencyException; use RuntimeException; use Traversable; use function array_keys; use function array_map; use function is_file; /** * List of supported Crypto Currencies codes and names using Binance as resource. */ final class CryptoCurrencies implements Currencies { /** * Map of known currencies indexed by code. * * @psalm-var non-empty-array<non-empty-string, array{ * symbol: non-empty-string, * minorUnit: positive-int|0 * }>|null */ private static ?array $currencies = null; public function contains(Currency $currency): bool { return isset($this->getCurrencies()[$currency->getCode()]); } public function subunitFor(Currency $currency): int { if (! $this->contains($currency)) { throw new UnknownCurrencyException('Cannot find ISO currency ' . $currency->getCode()); } return $this->getCurrencies()[$currency->getCode()]['minorUnit']; } /** * @psalm-return Traversable<int, Currency> */ public function getIterator(): Traversable { return new ArrayIterator( array_map( static function ($code) { return new Currency($code); }, array_keys($this->getCurrencies()) ) ); } /** * Returns a map of known currencies indexed by code. * * @psalm-return non-empty-array<non-empty-string, array{ * symbol: non-empty-string, * minorUnit: positive-int|0 * }> */ private function getCurrencies(): array { if (self::$currencies === null) { self::$currencies = $this->loadCurrencies(); } return self::$currencies; } /** * @psalm-return non-empty-array<non-empty-string, array{ * symbol: non-empty-string, * minorUnit: positive-int|0 * }> * * @psalm-suppress MoreSpecificReturnType do not specify all keys and values */ private function loadCurrencies(): array { $file = __DIR__ . '/../../resources/binance.php'; if (is_file($file)) { /** @psalm-suppress LessSpecificReturnStatement */ return require $file; } throw new RuntimeException('Failed to load currency ISO codes.'); } } src/Calculator.php 0000644 00000007245 15105703713 0010147 0 ustar 00 <?php declare(strict_types=1); namespace Money; use Money\Exception\InvalidArgumentException; /** * Money calculations abstracted away from the Money value object. * * @internal the calculator component is an internal detail of this library: it is only supposed to be replaced if * your system requires a custom architecture for operating on large numbers. */ interface Calculator { /** * Compare a to b. * * Retrieves a negative value if $a < $b. * Retrieves a positive value if $a > $b. * Retrieves zero if $a == $b * * @psalm-param numeric-string $a * @psalm-param numeric-string $b * * @psalm-pure */ public static function compare(string $a, string $b): int; /** * Add added to amount. * * @psalm-param numeric-string $amount * @psalm-param numeric-string $addend * * @psalm-return numeric-string * * @psalm-pure */ public static function add(string $amount, string $addend): string; /** * Subtract subtrahend from amount. * * @psalm-param numeric-string $amount * @psalm-param numeric-string $subtrahend * * @psalm-return numeric-string * * @psalm-pure */ public static function subtract(string $amount, string $subtrahend): string; /** * Multiply amount with multiplier. * * @psalm-param numeric-string $amount * @psalm-param numeric-string $multiplier * * @psalm-return numeric-string * * @psalm-pure */ public static function multiply(string $amount, string $multiplier): string; /** * Divide amount with divisor. * * @psalm-param numeric-string $amount * @psalm-param numeric-string $divisor * * @psalm-return numeric-string * * @throws InvalidArgumentException when $divisor is zero. * * @psalm-pure */ public static function divide(string $amount, string $divisor): string; /** * Round number to following integer. * * @psalm-param numeric-string $number * * @psalm-return numeric-string * * @psalm-pure */ public static function ceil(string $number): string; /** * Round number to preceding integer. * * @psalm-param numeric-string $number * * @psalm-return numeric-string * * @psalm-pure */ public static function floor(string $number): string; /** * Returns the absolute value of the number. * * @psalm-param numeric-string $number * * @psalm-return numeric-string * * @psalm-pure */ public static function absolute(string $number): string; /** * Round number, use rounding mode for tie-breaker. * * @psalm-param numeric-string $number * @psalm-param Money::ROUND_* $roundingMode * * @psalm-return numeric-string * * @psalm-pure */ public static function round(string $number, int $roundingMode): string; /** * Share amount among ratio / total portions. * * @psalm-param numeric-string $amount * @psalm-param numeric-string $ratio * @psalm-param numeric-string $total * * @psalm-return numeric-string * * @psalm-pure */ public static function share(string $amount, string $ratio, string $total): string; /** * Get the modulus of an amount. * * @psalm-param numeric-string $amount * @psalm-param numeric-string $divisor * * @psalm-return numeric-string * * @throws InvalidArgumentException when $divisor is zero. * * @psalm-pure */ public static function mod(string $amount, string $divisor): string; } src/MoneyParser.php 0000644 00000000527 15105703713 0010316 0 ustar 00 <?php declare(strict_types=1); namespace Money; /** * Parses a string into a Money object. */ interface MoneyParser { /** * Parses a string into a Money object (including currency). * * @throws Exception\ParserException */ public function parse(string $money, Currency|null $fallbackCurrency = null): Money; } README.md 0000644 00000007171 15105703713 0006033 0 ustar 00 # Money [](https://github.com/moneyphp/money/releases)  [](https://packagist.org/packages/moneyphp/money) [](mailto:team@moneyphp.org)  PHP library to make working with money safer, easier, and fun! > "If I had a dime for every time I've seen someone use FLOAT to store currency, I'd have $999.997634" -- [Bill Karwin](https://twitter.com/billkarwin/status/347561901460447232) In short: You shouldn't represent monetary values by a float. Wherever you need to represent money, use this Money value object. Since version 3.0 this library uses [strings internally](https://github.com/moneyphp/money/pull/136) in order to support unlimited integers. ```php <?php use Money\Money; $fiveEur = Money::EUR(500); $tenEur = $fiveEur->add($fiveEur); list($part1, $part2, $part3) = $tenEur->allocate([1, 1, 1]); assert($part1->equals(Money::EUR(334))); assert($part2->equals(Money::EUR(333))); assert($part3->equals(Money::EUR(333))); ``` The documentation is available at http://moneyphp.org ## Requirements This library requires the [BCMath PHP extension](https://www.php.net/manual/en/book.bc.php). There might be additional dependencies for specific feature, e.g. the Swap exchange implementation, check the documentation for more information. Version 4 requires PHP 8.0. For older version of PHP, use version 3 of this library. ## Install Via Composer ```bash $ composer require moneyphp/money ``` ## Features - JSON Serialization - Big integer support utilizing different, transparent calculation logic upon availability (bcmath, gmp, plain php) - Money formatting (including intl formatter) - Currency repositories (ISO currencies included) - Money exchange (including [Swap](http://swap.voutzinos.org) implementation) ## Documentation Please see the [official documentation](http://moneyphp.org). ## Testing We try to follow BDD and TDD, as such we use both [phpspec](http://www.phpspec.net) and [phpunit](https://phpunit.de) to test this library. ```bash $ composer test ``` ### Running the tests in Docker Money requires a set of dependencies, so you might want to run it in Docker. First, build the image locally: ```bash $ docker build -t moneyphp . ``` Then run the tests: ```bash $ docker run --rm -it -v $PWD:/app -w /app moneyphp vendor/bin/phpunit --exclude-group segmentation ``` ## Contributing We would love to see you helping us to make this library better and better. Please keep in mind we do not use suffixes and prefixes in class names, so not `CurrenciesInterface`, but `Currencies`. Other than that, Style CI will help you using the same code style as we are using. Please provide tests when creating a PR and clear descriptions of bugs when filing issues. ## Security If you discover any security related issues, please contact us at [team@moneyphp.org](mailto:team@moneyphp.org). ## License The MIT License (MIT). Please see [License File](LICENSE) for more information. ## Acknowledgements This library is heavily inspired by [Martin Fowler's Money pattern](http://martinfowler.com/eaaCatalog/money.html). A special remark goes to [Mathias Verraes](https://github.com/mathiasverraes), without his contributions, in code and via his [blog](http://verraes.net/#blog), this library would not be where it stands now. LICENSE 0000644 00000002237 15105703714 0005560 0 ustar 00 Copyright (c) 2011-2016 Mathias Verraes Copyright (c) 2016 Márk Sági-Kazár <mark.sagikazar@gmail.com> Copyright (c) 2016 Frederik Bosch <f.bosch@genkgo.nl> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. resources/generate-money-factory.php 0000644 00000003632 15105703714 0013662 0 ustar 00 <?php require __DIR__.'/../vendor/autoload.php'; use Money\Currencies; use Money\Currency; (static function (): void { $buffer = <<<'PHP' <?php declare(strict_types=1); namespace Money; use InvalidArgumentException; /** * This is a generated file. Do not edit it manually! * PHPDOC * @psalm-immutable */ trait MoneyFactory { /** * Convenience factory method for a Money object. * * <code> * $fiveDollar = Money::USD(500); * </code> * * @param array $arguments * @psalm-param non-empty-string $method * @psalm-param array{numeric-string|int} $arguments * * @throws InvalidArgumentException If amount is not integer(ish). * * @psalm-pure */ public static function __callStatic(string $method, array $arguments): Money { return new Money($arguments[0], new Currency($method)); } } PHP; $methodBuffer = ''; $iterator = new Currencies\AggregateCurrencies([ new Currencies\ISOCurrencies(), new Currencies\BitcoinCurrencies(), new Currencies\CryptoCurrencies(), ]); $currencies = array_unique([...$iterator]); usort($currencies, static fn (Currency $a, Currency $b): int => strcmp($a->getCode(), $b->getCode())); /** @var Currency[] $currencies */ foreach ($currencies as $currency) { $code = $currency->getCode(); if (is_numeric($code[0])) { preg_match('/^([0-9]*)(.*?)$/', $code, $extracted); $formatter = new \NumberFormatter('en', \NumberFormatter::SPELLOUT); $code = strtoupper(preg_replace('/\s+/', '', $formatter->format($extracted[1])) . $extracted[2]); } $methodBuffer .= sprintf(" * @method static Money %s(numeric-string|int \$amount)\n", $code); } $buffer = str_replace('PHPDOC', rtrim($methodBuffer), $buffer); file_put_contents(__DIR__.'/../src/MoneyFactory.php', $buffer); })(); resources/binance.php 0000644 00000063017 15105703714 0010700 0 ustar 00 <?php return array ( '1INCH' => array ( 'symbol' => '1INCH', 'minorUnit' => 8, ), 'AAVE' => array ( 'symbol' => 'AAVE', 'minorUnit' => 8, ), 'ACA' => array ( 'symbol' => 'ACA', 'minorUnit' => 8, ), 'ACH' => array ( 'symbol' => 'ACH', 'minorUnit' => 8, ), 'ACM' => array ( 'symbol' => 'ACM', 'minorUnit' => 8, ), 'ADA' => array ( 'symbol' => 'ADA', 'minorUnit' => 8, ), 'ADX' => array ( 'symbol' => 'ADX', 'minorUnit' => 8, ), 'AERGO' => array ( 'symbol' => 'AERGO', 'minorUnit' => 8, ), 'AGIX' => array ( 'symbol' => 'AGIX', 'minorUnit' => 8, ), 'AGLD' => array ( 'symbol' => 'AGLD', 'minorUnit' => 8, ), 'AION' => array ( 'symbol' => 'AION', 'minorUnit' => 8, ), 'AKRO' => array ( 'symbol' => 'AKRO', 'minorUnit' => 8, ), 'ALCX' => array ( 'symbol' => 'ALCX', 'minorUnit' => 8, ), 'ALGO' => array ( 'symbol' => 'ALGO', 'minorUnit' => 8, ), 'ALICE' => array ( 'symbol' => 'ALICE', 'minorUnit' => 8, ), 'ALPACA' => array ( 'symbol' => 'ALPACA', 'minorUnit' => 8, ), 'ALPHA' => array ( 'symbol' => 'ALPHA', 'minorUnit' => 8, ), 'ALPINE' => array ( 'symbol' => 'ALPINE', 'minorUnit' => 8, ), 'AMB' => array ( 'symbol' => 'AMB', 'minorUnit' => 8, ), 'AMP' => array ( 'symbol' => 'AMP', 'minorUnit' => 8, ), 'ANC' => array ( 'symbol' => 'ANC', 'minorUnit' => 8, ), 'ANKR' => array ( 'symbol' => 'ANKR', 'minorUnit' => 8, ), 'ANT' => array ( 'symbol' => 'ANT', 'minorUnit' => 8, ), 'APE' => array ( 'symbol' => 'APE', 'minorUnit' => 8, ), 'API3' => array ( 'symbol' => 'API3', 'minorUnit' => 8, ), 'APT' => array ( 'symbol' => 'APT', 'minorUnit' => 8, ), 'AR' => array ( 'symbol' => 'AR', 'minorUnit' => 8, ), 'ARDR' => array ( 'symbol' => 'ARDR', 'minorUnit' => 8, ), 'ARK' => array ( 'symbol' => 'ARK', 'minorUnit' => 8, ), 'ARPA' => array ( 'symbol' => 'ARPA', 'minorUnit' => 8, ), 'ASR' => array ( 'symbol' => 'ASR', 'minorUnit' => 8, ), 'AST' => array ( 'symbol' => 'AST', 'minorUnit' => 8, ), 'ASTR' => array ( 'symbol' => 'ASTR', 'minorUnit' => 8, ), 'ATA' => array ( 'symbol' => 'ATA', 'minorUnit' => 8, ), 'ATM' => array ( 'symbol' => 'ATM', 'minorUnit' => 8, ), 'ATOM' => array ( 'symbol' => 'ATOM', 'minorUnit' => 8, ), 'AUCTION' => array ( 'symbol' => 'AUCTION', 'minorUnit' => 8, ), 'AUDIO' => array ( 'symbol' => 'AUDIO', 'minorUnit' => 8, ), 'AUTO' => array ( 'symbol' => 'AUTO', 'minorUnit' => 8, ), 'AVA' => array ( 'symbol' => 'AVA', 'minorUnit' => 8, ), 'AVAX' => array ( 'symbol' => 'AVAX', 'minorUnit' => 8, ), 'AXS' => array ( 'symbol' => 'AXS', 'minorUnit' => 8, ), 'BADGER' => array ( 'symbol' => 'BADGER', 'minorUnit' => 8, ), 'BAKE' => array ( 'symbol' => 'BAKE', 'minorUnit' => 8, ), 'BAL' => array ( 'symbol' => 'BAL', 'minorUnit' => 8, ), 'BAND' => array ( 'symbol' => 'BAND', 'minorUnit' => 8, ), 'BAR' => array ( 'symbol' => 'BAR', 'minorUnit' => 8, ), 'BAT' => array ( 'symbol' => 'BAT', 'minorUnit' => 8, ), 'BCH' => array ( 'symbol' => 'BCH', 'minorUnit' => 8, ), 'BDOT' => array ( 'symbol' => 'BDOT', 'minorUnit' => 8, ), 'BEAM' => array ( 'symbol' => 'BEAM', 'minorUnit' => 8, ), 'BEL' => array ( 'symbol' => 'BEL', 'minorUnit' => 8, ), 'BETA' => array ( 'symbol' => 'BETA', 'minorUnit' => 8, ), 'BETH' => array ( 'symbol' => 'BETH', 'minorUnit' => 8, ), 'BICO' => array ( 'symbol' => 'BICO', 'minorUnit' => 8, ), 'BIDR' => array ( 'symbol' => 'BIDR', 'minorUnit' => 8, ), 'BIFI' => array ( 'symbol' => 'BIFI', 'minorUnit' => 8, ), 'BLZ' => array ( 'symbol' => 'BLZ', 'minorUnit' => 8, ), 'BNB' => array ( 'symbol' => 'BNB', 'minorUnit' => 8, ), 'BNT' => array ( 'symbol' => 'BNT', 'minorUnit' => 8, ), 'BNX' => array ( 'symbol' => 'BNX', 'minorUnit' => 8, ), 'BOND' => array ( 'symbol' => 'BOND', 'minorUnit' => 8, ), 'BSW' => array ( 'symbol' => 'BSW', 'minorUnit' => 8, ), 'BTC' => array ( 'symbol' => 'BTC', 'minorUnit' => 8, ), 'BTCST' => array ( 'symbol' => 'BTCST', 'minorUnit' => 8, ), 'BTS' => array ( 'symbol' => 'BTS', 'minorUnit' => 8, ), 'BTTC' => array ( 'symbol' => 'BTTC', 'minorUnit' => 8, ), 'BURGER' => array ( 'symbol' => 'BURGER', 'minorUnit' => 8, ), 'BUSD' => array ( 'symbol' => 'BUSD', 'minorUnit' => 8, ), 'C98' => array ( 'symbol' => 'C98', 'minorUnit' => 8, ), 'CAKE' => array ( 'symbol' => 'CAKE', 'minorUnit' => 8, ), 'CELO' => array ( 'symbol' => 'CELO', 'minorUnit' => 8, ), 'CELR' => array ( 'symbol' => 'CELR', 'minorUnit' => 8, ), 'CFX' => array ( 'symbol' => 'CFX', 'minorUnit' => 8, ), 'CHESS' => array ( 'symbol' => 'CHESS', 'minorUnit' => 8, ), 'CHR' => array ( 'symbol' => 'CHR', 'minorUnit' => 8, ), 'CHZ' => array ( 'symbol' => 'CHZ', 'minorUnit' => 8, ), 'CITY' => array ( 'symbol' => 'CITY', 'minorUnit' => 8, ), 'CKB' => array ( 'symbol' => 'CKB', 'minorUnit' => 8, ), 'CLV' => array ( 'symbol' => 'CLV', 'minorUnit' => 8, ), 'COCOS' => array ( 'symbol' => 'COCOS', 'minorUnit' => 8, ), 'COMP' => array ( 'symbol' => 'COMP', 'minorUnit' => 8, ), 'COS' => array ( 'symbol' => 'COS', 'minorUnit' => 8, ), 'COTI' => array ( 'symbol' => 'COTI', 'minorUnit' => 8, ), 'CREAM' => array ( 'symbol' => 'CREAM', 'minorUnit' => 8, ), 'CRV' => array ( 'symbol' => 'CRV', 'minorUnit' => 8, ), 'CTK' => array ( 'symbol' => 'CTK', 'minorUnit' => 8, ), 'CTSI' => array ( 'symbol' => 'CTSI', 'minorUnit' => 8, ), 'CTXC' => array ( 'symbol' => 'CTXC', 'minorUnit' => 8, ), 'CVC' => array ( 'symbol' => 'CVC', 'minorUnit' => 8, ), 'CVP' => array ( 'symbol' => 'CVP', 'minorUnit' => 8, ), 'CVX' => array ( 'symbol' => 'CVX', 'minorUnit' => 8, ), 'DAI' => array ( 'symbol' => 'DAI', 'minorUnit' => 8, ), 'DAR' => array ( 'symbol' => 'DAR', 'minorUnit' => 8, ), 'DASH' => array ( 'symbol' => 'DASH', 'minorUnit' => 8, ), 'DATA' => array ( 'symbol' => 'DATA', 'minorUnit' => 8, ), 'DCR' => array ( 'symbol' => 'DCR', 'minorUnit' => 8, ), 'DEGO' => array ( 'symbol' => 'DEGO', 'minorUnit' => 8, ), 'DENT' => array ( 'symbol' => 'DENT', 'minorUnit' => 8, ), 'DEXE' => array ( 'symbol' => 'DEXE', 'minorUnit' => 8, ), 'DF' => array ( 'symbol' => 'DF', 'minorUnit' => 8, ), 'DGB' => array ( 'symbol' => 'DGB', 'minorUnit' => 8, ), 'DIA' => array ( 'symbol' => 'DIA', 'minorUnit' => 8, ), 'DOCK' => array ( 'symbol' => 'DOCK', 'minorUnit' => 8, ), 'DODO' => array ( 'symbol' => 'DODO', 'minorUnit' => 8, ), 'DOGE' => array ( 'symbol' => 'DOGE', 'minorUnit' => 8, ), 'DOT' => array ( 'symbol' => 'DOT', 'minorUnit' => 8, ), 'DREP' => array ( 'symbol' => 'DREP', 'minorUnit' => 8, ), 'DUSK' => array ( 'symbol' => 'DUSK', 'minorUnit' => 8, ), 'DYDX' => array ( 'symbol' => 'DYDX', 'minorUnit' => 8, ), 'EGLD' => array ( 'symbol' => 'EGLD', 'minorUnit' => 8, ), 'ELF' => array ( 'symbol' => 'ELF', 'minorUnit' => 8, ), 'ENJ' => array ( 'symbol' => 'ENJ', 'minorUnit' => 8, ), 'ENS' => array ( 'symbol' => 'ENS', 'minorUnit' => 8, ), 'EOS' => array ( 'symbol' => 'EOS', 'minorUnit' => 8, ), 'EPX' => array ( 'symbol' => 'EPX', 'minorUnit' => 8, ), 'ETC' => array ( 'symbol' => 'ETC', 'minorUnit' => 8, ), 'ETH' => array ( 'symbol' => 'ETH', 'minorUnit' => 8, ), 'FARM' => array ( 'symbol' => 'FARM', 'minorUnit' => 8, ), 'FET' => array ( 'symbol' => 'FET', 'minorUnit' => 8, ), 'FIDA' => array ( 'symbol' => 'FIDA', 'minorUnit' => 8, ), 'FIL' => array ( 'symbol' => 'FIL', 'minorUnit' => 8, ), 'FIO' => array ( 'symbol' => 'FIO', 'minorUnit' => 8, ), 'FIRO' => array ( 'symbol' => 'FIRO', 'minorUnit' => 8, ), 'FIS' => array ( 'symbol' => 'FIS', 'minorUnit' => 8, ), 'FLM' => array ( 'symbol' => 'FLM', 'minorUnit' => 8, ), 'FLOW' => array ( 'symbol' => 'FLOW', 'minorUnit' => 8, ), 'FLUX' => array ( 'symbol' => 'FLUX', 'minorUnit' => 8, ), 'FOR' => array ( 'symbol' => 'FOR', 'minorUnit' => 8, ), 'FORTH' => array ( 'symbol' => 'FORTH', 'minorUnit' => 8, ), 'FRONT' => array ( 'symbol' => 'FRONT', 'minorUnit' => 8, ), 'FTM' => array ( 'symbol' => 'FTM', 'minorUnit' => 8, ), 'FTT' => array ( 'symbol' => 'FTT', 'minorUnit' => 8, ), 'FUN' => array ( 'symbol' => 'FUN', 'minorUnit' => 8, ), 'FXS' => array ( 'symbol' => 'FXS', 'minorUnit' => 8, ), 'GAL' => array ( 'symbol' => 'GAL', 'minorUnit' => 8, ), 'GALA' => array ( 'symbol' => 'GALA', 'minorUnit' => 8, ), 'GAS' => array ( 'symbol' => 'GAS', 'minorUnit' => 8, ), 'GHST' => array ( 'symbol' => 'GHST', 'minorUnit' => 8, ), 'GLM' => array ( 'symbol' => 'GLM', 'minorUnit' => 8, ), 'GLMR' => array ( 'symbol' => 'GLMR', 'minorUnit' => 8, ), 'GMT' => array ( 'symbol' => 'GMT', 'minorUnit' => 8, ), 'GMX' => array ( 'symbol' => 'GMX', 'minorUnit' => 8, ), 'GNO' => array ( 'symbol' => 'GNO', 'minorUnit' => 8, ), 'GRT' => array ( 'symbol' => 'GRT', 'minorUnit' => 8, ), 'GTC' => array ( 'symbol' => 'GTC', 'minorUnit' => 8, ), 'GTO' => array ( 'symbol' => 'GTO', 'minorUnit' => 8, ), 'HARD' => array ( 'symbol' => 'HARD', 'minorUnit' => 8, ), 'HBAR' => array ( 'symbol' => 'HBAR', 'minorUnit' => 8, ), 'HFT' => array ( 'symbol' => 'HFT', 'minorUnit' => 8, ), 'HIGH' => array ( 'symbol' => 'HIGH', 'minorUnit' => 8, ), 'HIVE' => array ( 'symbol' => 'HIVE', 'minorUnit' => 8, ), 'HNT' => array ( 'symbol' => 'HNT', 'minorUnit' => 8, ), 'HOOK' => array ( 'symbol' => 'HOOK', 'minorUnit' => 8, ), 'HOT' => array ( 'symbol' => 'HOT', 'minorUnit' => 8, ), 'ICP' => array ( 'symbol' => 'ICP', 'minorUnit' => 8, ), 'ICX' => array ( 'symbol' => 'ICX', 'minorUnit' => 8, ), 'IDEX' => array ( 'symbol' => 'IDEX', 'minorUnit' => 8, ), 'IDRT' => array ( 'symbol' => 'IDRT', 'minorUnit' => 8, ), 'ILV' => array ( 'symbol' => 'ILV', 'minorUnit' => 8, ), 'IMX' => array ( 'symbol' => 'IMX', 'minorUnit' => 8, ), 'INJ' => array ( 'symbol' => 'INJ', 'minorUnit' => 8, ), 'IOST' => array ( 'symbol' => 'IOST', 'minorUnit' => 8, ), 'IOTA' => array ( 'symbol' => 'IOTA', 'minorUnit' => 8, ), 'IOTX' => array ( 'symbol' => 'IOTX', 'minorUnit' => 8, ), 'IQ' => array ( 'symbol' => 'IQ', 'minorUnit' => 8, ), 'IRIS' => array ( 'symbol' => 'IRIS', 'minorUnit' => 8, ), 'JASMY' => array ( 'symbol' => 'JASMY', 'minorUnit' => 8, ), 'JOE' => array ( 'symbol' => 'JOE', 'minorUnit' => 8, ), 'JST' => array ( 'symbol' => 'JST', 'minorUnit' => 8, ), 'JUV' => array ( 'symbol' => 'JUV', 'minorUnit' => 8, ), 'KAVA' => array ( 'symbol' => 'KAVA', 'minorUnit' => 8, ), 'KDA' => array ( 'symbol' => 'KDA', 'minorUnit' => 8, ), 'KEY' => array ( 'symbol' => 'KEY', 'minorUnit' => 8, ), 'KLAY' => array ( 'symbol' => 'KLAY', 'minorUnit' => 8, ), 'KMD' => array ( 'symbol' => 'KMD', 'minorUnit' => 8, ), 'KNC' => array ( 'symbol' => 'KNC', 'minorUnit' => 8, ), 'KP3R' => array ( 'symbol' => 'KP3R', 'minorUnit' => 8, ), 'KSM' => array ( 'symbol' => 'KSM', 'minorUnit' => 8, ), 'LAZIO' => array ( 'symbol' => 'LAZIO', 'minorUnit' => 8, ), 'LDO' => array ( 'symbol' => 'LDO', 'minorUnit' => 8, ), 'LEVER' => array ( 'symbol' => 'LEVER', 'minorUnit' => 8, ), 'LINA' => array ( 'symbol' => 'LINA', 'minorUnit' => 8, ), 'LINK' => array ( 'symbol' => 'LINK', 'minorUnit' => 8, ), 'LIT' => array ( 'symbol' => 'LIT', 'minorUnit' => 8, ), 'LOKA' => array ( 'symbol' => 'LOKA', 'minorUnit' => 8, ), 'LOOM' => array ( 'symbol' => 'LOOM', 'minorUnit' => 8, ), 'LPT' => array ( 'symbol' => 'LPT', 'minorUnit' => 8, ), 'LRC' => array ( 'symbol' => 'LRC', 'minorUnit' => 8, ), 'LSK' => array ( 'symbol' => 'LSK', 'minorUnit' => 8, ), 'LTC' => array ( 'symbol' => 'LTC', 'minorUnit' => 8, ), 'LTO' => array ( 'symbol' => 'LTO', 'minorUnit' => 8, ), 'LUNA' => array ( 'symbol' => 'LUNA', 'minorUnit' => 8, ), 'LUNC' => array ( 'symbol' => 'LUNC', 'minorUnit' => 8, ), 'MAGIC' => array ( 'symbol' => 'MAGIC', 'minorUnit' => 8, ), 'MANA' => array ( 'symbol' => 'MANA', 'minorUnit' => 8, ), 'MASK' => array ( 'symbol' => 'MASK', 'minorUnit' => 8, ), 'MATIC' => array ( 'symbol' => 'MATIC', 'minorUnit' => 8, ), 'MBL' => array ( 'symbol' => 'MBL', 'minorUnit' => 8, ), 'MBOX' => array ( 'symbol' => 'MBOX', 'minorUnit' => 8, ), 'MC' => array ( 'symbol' => 'MC', 'minorUnit' => 8, ), 'MDT' => array ( 'symbol' => 'MDT', 'minorUnit' => 8, ), 'MDX' => array ( 'symbol' => 'MDX', 'minorUnit' => 8, ), 'MFT' => array ( 'symbol' => 'MFT', 'minorUnit' => 8, ), 'MINA' => array ( 'symbol' => 'MINA', 'minorUnit' => 8, ), 'MIR' => array ( 'symbol' => 'MIR', 'minorUnit' => 8, ), 'MITH' => array ( 'symbol' => 'MITH', 'minorUnit' => 8, ), 'MKR' => array ( 'symbol' => 'MKR', 'minorUnit' => 8, ), 'MLN' => array ( 'symbol' => 'MLN', 'minorUnit' => 8, ), 'MOB' => array ( 'symbol' => 'MOB', 'minorUnit' => 8, ), 'MOVR' => array ( 'symbol' => 'MOVR', 'minorUnit' => 8, ), 'MTL' => array ( 'symbol' => 'MTL', 'minorUnit' => 8, ), 'MULTI' => array ( 'symbol' => 'MULTI', 'minorUnit' => 8, ), 'NEAR' => array ( 'symbol' => 'NEAR', 'minorUnit' => 8, ), 'NEBL' => array ( 'symbol' => 'NEBL', 'minorUnit' => 8, ), 'NEO' => array ( 'symbol' => 'NEO', 'minorUnit' => 8, ), 'NEXO' => array ( 'symbol' => 'NEXO', 'minorUnit' => 8, ), 'NKN' => array ( 'symbol' => 'NKN', 'minorUnit' => 8, ), 'NMR' => array ( 'symbol' => 'NMR', 'minorUnit' => 8, ), 'NULS' => array ( 'symbol' => 'NULS', 'minorUnit' => 8, ), 'OAX' => array ( 'symbol' => 'OAX', 'minorUnit' => 8, ), 'OCEAN' => array ( 'symbol' => 'OCEAN', 'minorUnit' => 8, ), 'OG' => array ( 'symbol' => 'OG', 'minorUnit' => 8, ), 'OGN' => array ( 'symbol' => 'OGN', 'minorUnit' => 8, ), 'OM' => array ( 'symbol' => 'OM', 'minorUnit' => 8, ), 'OMG' => array ( 'symbol' => 'OMG', 'minorUnit' => 8, ), 'ONE' => array ( 'symbol' => 'ONE', 'minorUnit' => 8, ), 'ONG' => array ( 'symbol' => 'ONG', 'minorUnit' => 8, ), 'ONT' => array ( 'symbol' => 'ONT', 'minorUnit' => 8, ), 'OOKI' => array ( 'symbol' => 'OOKI', 'minorUnit' => 8, ), 'OP' => array ( 'symbol' => 'OP', 'minorUnit' => 8, ), 'ORN' => array ( 'symbol' => 'ORN', 'minorUnit' => 8, ), 'OSMO' => array ( 'symbol' => 'OSMO', 'minorUnit' => 8, ), 'OXT' => array ( 'symbol' => 'OXT', 'minorUnit' => 8, ), 'PAXG' => array ( 'symbol' => 'PAXG', 'minorUnit' => 8, ), 'PEOPLE' => array ( 'symbol' => 'PEOPLE', 'minorUnit' => 8, ), 'PERL' => array ( 'symbol' => 'PERL', 'minorUnit' => 8, ), 'PERP' => array ( 'symbol' => 'PERP', 'minorUnit' => 8, ), 'PHA' => array ( 'symbol' => 'PHA', 'minorUnit' => 8, ), 'PHB' => array ( 'symbol' => 'PHB', 'minorUnit' => 8, ), 'PIVX' => array ( 'symbol' => 'PIVX', 'minorUnit' => 8, ), 'PLA' => array ( 'symbol' => 'PLA', 'minorUnit' => 8, ), 'PNT' => array ( 'symbol' => 'PNT', 'minorUnit' => 8, ), 'POLS' => array ( 'symbol' => 'POLS', 'minorUnit' => 8, ), 'POLYX' => array ( 'symbol' => 'POLYX', 'minorUnit' => 8, ), 'POND' => array ( 'symbol' => 'POND', 'minorUnit' => 8, ), 'PORTO' => array ( 'symbol' => 'PORTO', 'minorUnit' => 8, ), 'POWR' => array ( 'symbol' => 'POWR', 'minorUnit' => 8, ), 'PROM' => array ( 'symbol' => 'PROM', 'minorUnit' => 8, ), 'PROS' => array ( 'symbol' => 'PROS', 'minorUnit' => 8, ), 'PSG' => array ( 'symbol' => 'PSG', 'minorUnit' => 8, ), 'PUNDIX' => array ( 'symbol' => 'PUNDIX', 'minorUnit' => 8, ), 'PYR' => array ( 'symbol' => 'PYR', 'minorUnit' => 8, ), 'QI' => array ( 'symbol' => 'QI', 'minorUnit' => 8, ), 'QKC' => array ( 'symbol' => 'QKC', 'minorUnit' => 8, ), 'QLC' => array ( 'symbol' => 'QLC', 'minorUnit' => 8, ), 'QNT' => array ( 'symbol' => 'QNT', 'minorUnit' => 8, ), 'QTUM' => array ( 'symbol' => 'QTUM', 'minorUnit' => 8, ), 'QUICK' => array ( 'symbol' => 'QUICK', 'minorUnit' => 8, ), 'RAD' => array ( 'symbol' => 'RAD', 'minorUnit' => 8, ), 'RARE' => array ( 'symbol' => 'RARE', 'minorUnit' => 8, ), 'RAY' => array ( 'symbol' => 'RAY', 'minorUnit' => 8, ), 'REEF' => array ( 'symbol' => 'REEF', 'minorUnit' => 8, ), 'REI' => array ( 'symbol' => 'REI', 'minorUnit' => 8, ), 'REN' => array ( 'symbol' => 'REN', 'minorUnit' => 8, ), 'REP' => array ( 'symbol' => 'REP', 'minorUnit' => 8, ), 'REQ' => array ( 'symbol' => 'REQ', 'minorUnit' => 8, ), 'RIF' => array ( 'symbol' => 'RIF', 'minorUnit' => 8, ), 'RLC' => array ( 'symbol' => 'RLC', 'minorUnit' => 8, ), 'RNDR' => array ( 'symbol' => 'RNDR', 'minorUnit' => 8, ), 'ROSE' => array ( 'symbol' => 'ROSE', 'minorUnit' => 8, ), 'RSR' => array ( 'symbol' => 'RSR', 'minorUnit' => 8, ), 'RUNE' => array ( 'symbol' => 'RUNE', 'minorUnit' => 8, ), 'RVN' => array ( 'symbol' => 'RVN', 'minorUnit' => 8, ), 'SAND' => array ( 'symbol' => 'SAND', 'minorUnit' => 8, ), 'SANTOS' => array ( 'symbol' => 'SANTOS', 'minorUnit' => 8, ), 'SC' => array ( 'symbol' => 'SC', 'minorUnit' => 8, ), 'SCRT' => array ( 'symbol' => 'SCRT', 'minorUnit' => 8, ), 'SFP' => array ( 'symbol' => 'SFP', 'minorUnit' => 8, ), 'SHIB' => array ( 'symbol' => 'SHIB', 'minorUnit' => 8, ), 'SKL' => array ( 'symbol' => 'SKL', 'minorUnit' => 8, ), 'SLP' => array ( 'symbol' => 'SLP', 'minorUnit' => 8, ), 'SNM' => array ( 'symbol' => 'SNM', 'minorUnit' => 8, ), 'SNT' => array ( 'symbol' => 'SNT', 'minorUnit' => 8, ), 'SNX' => array ( 'symbol' => 'SNX', 'minorUnit' => 8, ), 'SOL' => array ( 'symbol' => 'SOL', 'minorUnit' => 8, ), 'SPELL' => array ( 'symbol' => 'SPELL', 'minorUnit' => 8, ), 'SRM' => array ( 'symbol' => 'SRM', 'minorUnit' => 8, ), 'SSV' => array ( 'symbol' => 'SSV', 'minorUnit' => 8, ), 'STEEM' => array ( 'symbol' => 'STEEM', 'minorUnit' => 8, ), 'STG' => array ( 'symbol' => 'STG', 'minorUnit' => 8, ), 'STMX' => array ( 'symbol' => 'STMX', 'minorUnit' => 8, ), 'STORJ' => array ( 'symbol' => 'STORJ', 'minorUnit' => 8, ), 'STPT' => array ( 'symbol' => 'STPT', 'minorUnit' => 8, ), 'STRAX' => array ( 'symbol' => 'STRAX', 'minorUnit' => 8, ), 'STX' => array ( 'symbol' => 'STX', 'minorUnit' => 8, ), 'SUN' => array ( 'symbol' => 'SUN', 'minorUnit' => 8, ), 'SUPER' => array ( 'symbol' => 'SUPER', 'minorUnit' => 8, ), 'SUSHI' => array ( 'symbol' => 'SUSHI', 'minorUnit' => 8, ), 'SXP' => array ( 'symbol' => 'SXP', 'minorUnit' => 8, ), 'SYS' => array ( 'symbol' => 'SYS', 'minorUnit' => 8, ), 'T' => array ( 'symbol' => 'T', 'minorUnit' => 8, ), 'TFUEL' => array ( 'symbol' => 'TFUEL', 'minorUnit' => 8, ), 'THETA' => array ( 'symbol' => 'THETA', 'minorUnit' => 8, ), 'TKO' => array ( 'symbol' => 'TKO', 'minorUnit' => 8, ), 'TLM' => array ( 'symbol' => 'TLM', 'minorUnit' => 8, ), 'TOMO' => array ( 'symbol' => 'TOMO', 'minorUnit' => 8, ), 'TORN' => array ( 'symbol' => 'TORN', 'minorUnit' => 8, ), 'TRB' => array ( 'symbol' => 'TRB', 'minorUnit' => 8, ), 'TRIBE' => array ( 'symbol' => 'TRIBE', 'minorUnit' => 8, ), 'TROY' => array ( 'symbol' => 'TROY', 'minorUnit' => 8, ), 'TRU' => array ( 'symbol' => 'TRU', 'minorUnit' => 8, ), 'TRX' => array ( 'symbol' => 'TRX', 'minorUnit' => 8, ), 'TVK' => array ( 'symbol' => 'TVK', 'minorUnit' => 8, ), 'TWT' => array ( 'symbol' => 'TWT', 'minorUnit' => 8, ), 'UFT' => array ( 'symbol' => 'UFT', 'minorUnit' => 8, ), 'UMA' => array ( 'symbol' => 'UMA', 'minorUnit' => 8, ), 'UNFI' => array ( 'symbol' => 'UNFI', 'minorUnit' => 8, ), 'UNI' => array ( 'symbol' => 'UNI', 'minorUnit' => 8, ), 'USDT' => array ( 'symbol' => 'USDT', 'minorUnit' => 8, ), 'USTC' => array ( 'symbol' => 'USTC', 'minorUnit' => 8, ), 'UTK' => array ( 'symbol' => 'UTK', 'minorUnit' => 8, ), 'VAI' => array ( 'symbol' => 'VAI', 'minorUnit' => 8, ), 'VET' => array ( 'symbol' => 'VET', 'minorUnit' => 8, ), 'VGX' => array ( 'symbol' => 'VGX', 'minorUnit' => 8, ), 'VIB' => array ( 'symbol' => 'VIB', 'minorUnit' => 8, ), 'VIDT' => array ( 'symbol' => 'VIDT', 'minorUnit' => 8, ), 'VITE' => array ( 'symbol' => 'VITE', 'minorUnit' => 8, ), 'VOXEL' => array ( 'symbol' => 'VOXEL', 'minorUnit' => 8, ), 'VTHO' => array ( 'symbol' => 'VTHO', 'minorUnit' => 8, ), 'WABI' => array ( 'symbol' => 'WABI', 'minorUnit' => 8, ), 'WAN' => array ( 'symbol' => 'WAN', 'minorUnit' => 8, ), 'WAVES' => array ( 'symbol' => 'WAVES', 'minorUnit' => 8, ), 'WAXP' => array ( 'symbol' => 'WAXP', 'minorUnit' => 8, ), 'WBTC' => array ( 'symbol' => 'WBTC', 'minorUnit' => 8, ), 'WIN' => array ( 'symbol' => 'WIN', 'minorUnit' => 8, ), 'WING' => array ( 'symbol' => 'WING', 'minorUnit' => 8, ), 'WNXM' => array ( 'symbol' => 'WNXM', 'minorUnit' => 8, ), 'WOO' => array ( 'symbol' => 'WOO', 'minorUnit' => 8, ), 'WRX' => array ( 'symbol' => 'WRX', 'minorUnit' => 8, ), 'WTC' => array ( 'symbol' => 'WTC', 'minorUnit' => 8, ), 'XEC' => array ( 'symbol' => 'XEC', 'minorUnit' => 8, ), 'XEM' => array ( 'symbol' => 'XEM', 'minorUnit' => 8, ), 'XLM' => array ( 'symbol' => 'XLM', 'minorUnit' => 8, ), 'XMR' => array ( 'symbol' => 'XMR', 'minorUnit' => 8, ), 'XNO' => array ( 'symbol' => 'XNO', 'minorUnit' => 8, ), 'XRP' => array ( 'symbol' => 'XRP', 'minorUnit' => 8, ), 'XTZ' => array ( 'symbol' => 'XTZ', 'minorUnit' => 8, ), 'XVG' => array ( 'symbol' => 'XVG', 'minorUnit' => 8, ), 'XVS' => array ( 'symbol' => 'XVS', 'minorUnit' => 8, ), 'YFI' => array ( 'symbol' => 'YFI', 'minorUnit' => 8, ), 'YFII' => array ( 'symbol' => 'YFII', 'minorUnit' => 8, ), 'YGG' => array ( 'symbol' => 'YGG', 'minorUnit' => 8, ), 'ZEC' => array ( 'symbol' => 'ZEC', 'minorUnit' => 8, ), 'ZEN' => array ( 'symbol' => 'ZEN', 'minorUnit' => 8, ), 'ZIL' => array ( 'symbol' => 'ZIL', 'minorUnit' => 8, ), 'ZRX' => array ( 'symbol' => 'ZRX', 'minorUnit' => 8, ), ); resources/currency.php 0000644 00000061622 15105703714 0011133 0 ustar 00 <?php return array ( 'AED' => array ( 'alphabeticCode' => 'AED', 'currency' => 'UAE Dirham', 'minorUnit' => 2, 'numericCode' => 784, ), 'AFN' => array ( 'alphabeticCode' => 'AFN', 'currency' => 'Afghani', 'minorUnit' => 2, 'numericCode' => 971, ), 'ALL' => array ( 'alphabeticCode' => 'ALL', 'currency' => 'Lek', 'minorUnit' => 2, 'numericCode' => 8, ), 'AMD' => array ( 'alphabeticCode' => 'AMD', 'currency' => 'Armenian Dram', 'minorUnit' => 2, 'numericCode' => 51, ), 'ANG' => array ( 'alphabeticCode' => 'ANG', 'currency' => 'Netherlands Antillean Guilder', 'minorUnit' => 2, 'numericCode' => 532, ), 'AOA' => array ( 'alphabeticCode' => 'AOA', 'currency' => 'Kwanza', 'minorUnit' => 2, 'numericCode' => 973, ), 'ARS' => array ( 'alphabeticCode' => 'ARS', 'currency' => 'Argentine Peso', 'minorUnit' => 2, 'numericCode' => 32, ), 'AUD' => array ( 'alphabeticCode' => 'AUD', 'currency' => 'Australian Dollar', 'minorUnit' => 2, 'numericCode' => 36, ), 'AWG' => array ( 'alphabeticCode' => 'AWG', 'currency' => 'Aruban Florin', 'minorUnit' => 2, 'numericCode' => 533, ), 'AZN' => array ( 'alphabeticCode' => 'AZN', 'currency' => 'Azerbaijan Manat', 'minorUnit' => 2, 'numericCode' => 944, ), 'BAM' => array ( 'alphabeticCode' => 'BAM', 'currency' => 'Convertible Mark', 'minorUnit' => 2, 'numericCode' => 977, ), 'BBD' => array ( 'alphabeticCode' => 'BBD', 'currency' => 'Barbados Dollar', 'minorUnit' => 2, 'numericCode' => 52, ), 'BDT' => array ( 'alphabeticCode' => 'BDT', 'currency' => 'Taka', 'minorUnit' => 2, 'numericCode' => 50, ), 'BGN' => array ( 'alphabeticCode' => 'BGN', 'currency' => 'Bulgarian Lev', 'minorUnit' => 2, 'numericCode' => 975, ), 'BHD' => array ( 'alphabeticCode' => 'BHD', 'currency' => 'Bahraini Dinar', 'minorUnit' => 3, 'numericCode' => 48, ), 'BIF' => array ( 'alphabeticCode' => 'BIF', 'currency' => 'Burundi Franc', 'minorUnit' => 0, 'numericCode' => 108, ), 'BMD' => array ( 'alphabeticCode' => 'BMD', 'currency' => 'Bermudian Dollar', 'minorUnit' => 2, 'numericCode' => 60, ), 'BND' => array ( 'alphabeticCode' => 'BND', 'currency' => 'Brunei Dollar', 'minorUnit' => 2, 'numericCode' => 96, ), 'BOB' => array ( 'alphabeticCode' => 'BOB', 'currency' => 'Boliviano', 'minorUnit' => 2, 'numericCode' => 68, ), 'BOV' => array ( 'alphabeticCode' => 'BOV', 'currency' => 'Mvdol', 'minorUnit' => 2, 'numericCode' => 984, ), 'BRL' => array ( 'alphabeticCode' => 'BRL', 'currency' => 'Brazilian Real', 'minorUnit' => 2, 'numericCode' => 986, ), 'BSD' => array ( 'alphabeticCode' => 'BSD', 'currency' => 'Bahamian Dollar', 'minorUnit' => 2, 'numericCode' => 44, ), 'BTN' => array ( 'alphabeticCode' => 'BTN', 'currency' => 'Ngultrum', 'minorUnit' => 2, 'numericCode' => 64, ), 'BWP' => array ( 'alphabeticCode' => 'BWP', 'currency' => 'Pula', 'minorUnit' => 2, 'numericCode' => 72, ), 'BYN' => array ( 'alphabeticCode' => 'BYN', 'currency' => 'Belarusian Ruble', 'minorUnit' => 2, 'numericCode' => 933, ), 'BZD' => array ( 'alphabeticCode' => 'BZD', 'currency' => 'Belize Dollar', 'minorUnit' => 2, 'numericCode' => 84, ), 'CAD' => array ( 'alphabeticCode' => 'CAD', 'currency' => 'Canadian Dollar', 'minorUnit' => 2, 'numericCode' => 124, ), 'CDF' => array ( 'alphabeticCode' => 'CDF', 'currency' => 'Congolese Franc', 'minorUnit' => 2, 'numericCode' => 976, ), 'CHE' => array ( 'alphabeticCode' => 'CHE', 'currency' => 'WIR Euro', 'minorUnit' => 2, 'numericCode' => 947, ), 'CHF' => array ( 'alphabeticCode' => 'CHF', 'currency' => 'Swiss Franc', 'minorUnit' => 2, 'numericCode' => 756, ), 'CHW' => array ( 'alphabeticCode' => 'CHW', 'currency' => 'WIR Franc', 'minorUnit' => 2, 'numericCode' => 948, ), 'CLF' => array ( 'alphabeticCode' => 'CLF', 'currency' => 'Unidad de Fomento', 'minorUnit' => 4, 'numericCode' => 990, ), 'CLP' => array ( 'alphabeticCode' => 'CLP', 'currency' => 'Chilean Peso', 'minorUnit' => 0, 'numericCode' => 152, ), 'CNY' => array ( 'alphabeticCode' => 'CNY', 'currency' => 'Yuan Renminbi', 'minorUnit' => 2, 'numericCode' => 156, ), 'COP' => array ( 'alphabeticCode' => 'COP', 'currency' => 'Colombian Peso', 'minorUnit' => 2, 'numericCode' => 170, ), 'COU' => array ( 'alphabeticCode' => 'COU', 'currency' => 'Unidad de Valor Real', 'minorUnit' => 2, 'numericCode' => 970, ), 'CRC' => array ( 'alphabeticCode' => 'CRC', 'currency' => 'Costa Rican Colon', 'minorUnit' => 2, 'numericCode' => 188, ), 'CUC' => array ( 'alphabeticCode' => 'CUC', 'currency' => 'Peso Convertible', 'minorUnit' => 2, 'numericCode' => 931, ), 'CUP' => array ( 'alphabeticCode' => 'CUP', 'currency' => 'Cuban Peso', 'minorUnit' => 2, 'numericCode' => 192, ), 'CVE' => array ( 'alphabeticCode' => 'CVE', 'currency' => 'Cabo Verde Escudo', 'minorUnit' => 2, 'numericCode' => 132, ), 'CZK' => array ( 'alphabeticCode' => 'CZK', 'currency' => 'Czech Koruna', 'minorUnit' => 2, 'numericCode' => 203, ), 'DJF' => array ( 'alphabeticCode' => 'DJF', 'currency' => 'Djibouti Franc', 'minorUnit' => 0, 'numericCode' => 262, ), 'DKK' => array ( 'alphabeticCode' => 'DKK', 'currency' => 'Danish Krone', 'minorUnit' => 2, 'numericCode' => 208, ), 'DOP' => array ( 'alphabeticCode' => 'DOP', 'currency' => 'Dominican Peso', 'minorUnit' => 2, 'numericCode' => 214, ), 'DZD' => array ( 'alphabeticCode' => 'DZD', 'currency' => 'Algerian Dinar', 'minorUnit' => 2, 'numericCode' => 12, ), 'EGP' => array ( 'alphabeticCode' => 'EGP', 'currency' => 'Egyptian Pound', 'minorUnit' => 2, 'numericCode' => 818, ), 'ERN' => array ( 'alphabeticCode' => 'ERN', 'currency' => 'Nakfa', 'minorUnit' => 2, 'numericCode' => 232, ), 'ETB' => array ( 'alphabeticCode' => 'ETB', 'currency' => 'Ethiopian Birr', 'minorUnit' => 2, 'numericCode' => 230, ), 'EUR' => array ( 'alphabeticCode' => 'EUR', 'currency' => 'Euro', 'minorUnit' => 2, 'numericCode' => 978, ), 'FJD' => array ( 'alphabeticCode' => 'FJD', 'currency' => 'Fiji Dollar', 'minorUnit' => 2, 'numericCode' => 242, ), 'FKP' => array ( 'alphabeticCode' => 'FKP', 'currency' => 'Falkland Islands Pound', 'minorUnit' => 2, 'numericCode' => 238, ), 'GBP' => array ( 'alphabeticCode' => 'GBP', 'currency' => 'Pound Sterling', 'minorUnit' => 2, 'numericCode' => 826, ), 'GEL' => array ( 'alphabeticCode' => 'GEL', 'currency' => 'Lari', 'minorUnit' => 2, 'numericCode' => 981, ), 'GHS' => array ( 'alphabeticCode' => 'GHS', 'currency' => 'Ghana Cedi', 'minorUnit' => 2, 'numericCode' => 936, ), 'GIP' => array ( 'alphabeticCode' => 'GIP', 'currency' => 'Gibraltar Pound', 'minorUnit' => 2, 'numericCode' => 292, ), 'GMD' => array ( 'alphabeticCode' => 'GMD', 'currency' => 'Dalasi', 'minorUnit' => 2, 'numericCode' => 270, ), 'GNF' => array ( 'alphabeticCode' => 'GNF', 'currency' => 'Guinean Franc', 'minorUnit' => 0, 'numericCode' => 324, ), 'GTQ' => array ( 'alphabeticCode' => 'GTQ', 'currency' => 'Quetzal', 'minorUnit' => 2, 'numericCode' => 320, ), 'GYD' => array ( 'alphabeticCode' => 'GYD', 'currency' => 'Guyana Dollar', 'minorUnit' => 2, 'numericCode' => 328, ), 'HKD' => array ( 'alphabeticCode' => 'HKD', 'currency' => 'Hong Kong Dollar', 'minorUnit' => 2, 'numericCode' => 344, ), 'HNL' => array ( 'alphabeticCode' => 'HNL', 'currency' => 'Lempira', 'minorUnit' => 2, 'numericCode' => 340, ), 'HTG' => array ( 'alphabeticCode' => 'HTG', 'currency' => 'Gourde', 'minorUnit' => 2, 'numericCode' => 332, ), 'HUF' => array ( 'alphabeticCode' => 'HUF', 'currency' => 'Forint', 'minorUnit' => 2, 'numericCode' => 348, ), 'IDR' => array ( 'alphabeticCode' => 'IDR', 'currency' => 'Rupiah', 'minorUnit' => 2, 'numericCode' => 360, ), 'ILS' => array ( 'alphabeticCode' => 'ILS', 'currency' => 'New Israeli Sheqel', 'minorUnit' => 2, 'numericCode' => 376, ), 'INR' => array ( 'alphabeticCode' => 'INR', 'currency' => 'Indian Rupee', 'minorUnit' => 2, 'numericCode' => 356, ), 'IQD' => array ( 'alphabeticCode' => 'IQD', 'currency' => 'Iraqi Dinar', 'minorUnit' => 3, 'numericCode' => 368, ), 'IRR' => array ( 'alphabeticCode' => 'IRR', 'currency' => 'Iranian Rial', 'minorUnit' => 2, 'numericCode' => 364, ), 'ISK' => array ( 'alphabeticCode' => 'ISK', 'currency' => 'Iceland Krona', 'minorUnit' => 0, 'numericCode' => 352, ), 'JMD' => array ( 'alphabeticCode' => 'JMD', 'currency' => 'Jamaican Dollar', 'minorUnit' => 2, 'numericCode' => 388, ), 'JOD' => array ( 'alphabeticCode' => 'JOD', 'currency' => 'Jordanian Dinar', 'minorUnit' => 3, 'numericCode' => 400, ), 'JPY' => array ( 'alphabeticCode' => 'JPY', 'currency' => 'Yen', 'minorUnit' => 0, 'numericCode' => 392, ), 'KES' => array ( 'alphabeticCode' => 'KES', 'currency' => 'Kenyan Shilling', 'minorUnit' => 2, 'numericCode' => 404, ), 'KGS' => array ( 'alphabeticCode' => 'KGS', 'currency' => 'Som', 'minorUnit' => 2, 'numericCode' => 417, ), 'KHR' => array ( 'alphabeticCode' => 'KHR', 'currency' => 'Riel', 'minorUnit' => 2, 'numericCode' => 116, ), 'KMF' => array ( 'alphabeticCode' => 'KMF', 'currency' => 'Comorian Franc ', 'minorUnit' => 0, 'numericCode' => 174, ), 'KPW' => array ( 'alphabeticCode' => 'KPW', 'currency' => 'North Korean Won', 'minorUnit' => 2, 'numericCode' => 408, ), 'KRW' => array ( 'alphabeticCode' => 'KRW', 'currency' => 'Won', 'minorUnit' => 0, 'numericCode' => 410, ), 'KWD' => array ( 'alphabeticCode' => 'KWD', 'currency' => 'Kuwaiti Dinar', 'minorUnit' => 3, 'numericCode' => 414, ), 'KYD' => array ( 'alphabeticCode' => 'KYD', 'currency' => 'Cayman Islands Dollar', 'minorUnit' => 2, 'numericCode' => 136, ), 'KZT' => array ( 'alphabeticCode' => 'KZT', 'currency' => 'Tenge', 'minorUnit' => 2, 'numericCode' => 398, ), 'LAK' => array ( 'alphabeticCode' => 'LAK', 'currency' => 'Lao Kip', 'minorUnit' => 2, 'numericCode' => 418, ), 'LBP' => array ( 'alphabeticCode' => 'LBP', 'currency' => 'Lebanese Pound', 'minorUnit' => 2, 'numericCode' => 422, ), 'LKR' => array ( 'alphabeticCode' => 'LKR', 'currency' => 'Sri Lanka Rupee', 'minorUnit' => 2, 'numericCode' => 144, ), 'LRD' => array ( 'alphabeticCode' => 'LRD', 'currency' => 'Liberian Dollar', 'minorUnit' => 2, 'numericCode' => 430, ), 'LSL' => array ( 'alphabeticCode' => 'LSL', 'currency' => 'Loti', 'minorUnit' => 2, 'numericCode' => 426, ), 'LYD' => array ( 'alphabeticCode' => 'LYD', 'currency' => 'Libyan Dinar', 'minorUnit' => 3, 'numericCode' => 434, ), 'MAD' => array ( 'alphabeticCode' => 'MAD', 'currency' => 'Moroccan Dirham', 'minorUnit' => 2, 'numericCode' => 504, ), 'MDL' => array ( 'alphabeticCode' => 'MDL', 'currency' => 'Moldovan Leu', 'minorUnit' => 2, 'numericCode' => 498, ), 'MGA' => array ( 'alphabeticCode' => 'MGA', 'currency' => 'Malagasy Ariary', 'minorUnit' => 2, 'numericCode' => 969, ), 'MKD' => array ( 'alphabeticCode' => 'MKD', 'currency' => 'Denar', 'minorUnit' => 2, 'numericCode' => 807, ), 'MMK' => array ( 'alphabeticCode' => 'MMK', 'currency' => 'Kyat', 'minorUnit' => 2, 'numericCode' => 104, ), 'MNT' => array ( 'alphabeticCode' => 'MNT', 'currency' => 'Tugrik', 'minorUnit' => 2, 'numericCode' => 496, ), 'MOP' => array ( 'alphabeticCode' => 'MOP', 'currency' => 'Pataca', 'minorUnit' => 2, 'numericCode' => 446, ), 'MRU' => array ( 'alphabeticCode' => 'MRU', 'currency' => 'Ouguiya', 'minorUnit' => 2, 'numericCode' => 929, ), 'MUR' => array ( 'alphabeticCode' => 'MUR', 'currency' => 'Mauritius Rupee', 'minorUnit' => 2, 'numericCode' => 480, ), 'MVR' => array ( 'alphabeticCode' => 'MVR', 'currency' => 'Rufiyaa', 'minorUnit' => 2, 'numericCode' => 462, ), 'MWK' => array ( 'alphabeticCode' => 'MWK', 'currency' => 'Malawi Kwacha', 'minorUnit' => 2, 'numericCode' => 454, ), 'MXN' => array ( 'alphabeticCode' => 'MXN', 'currency' => 'Mexican Peso', 'minorUnit' => 2, 'numericCode' => 484, ), 'MXV' => array ( 'alphabeticCode' => 'MXV', 'currency' => 'Mexican Unidad de Inversion (UDI)', 'minorUnit' => 2, 'numericCode' => 979, ), 'MYR' => array ( 'alphabeticCode' => 'MYR', 'currency' => 'Malaysian Ringgit', 'minorUnit' => 2, 'numericCode' => 458, ), 'MZN' => array ( 'alphabeticCode' => 'MZN', 'currency' => 'Mozambique Metical', 'minorUnit' => 2, 'numericCode' => 943, ), 'NAD' => array ( 'alphabeticCode' => 'NAD', 'currency' => 'Namibia Dollar', 'minorUnit' => 2, 'numericCode' => 516, ), 'NGN' => array ( 'alphabeticCode' => 'NGN', 'currency' => 'Naira', 'minorUnit' => 2, 'numericCode' => 566, ), 'NIO' => array ( 'alphabeticCode' => 'NIO', 'currency' => 'Cordoba Oro', 'minorUnit' => 2, 'numericCode' => 558, ), 'NOK' => array ( 'alphabeticCode' => 'NOK', 'currency' => 'Norwegian Krone', 'minorUnit' => 2, 'numericCode' => 578, ), 'NPR' => array ( 'alphabeticCode' => 'NPR', 'currency' => 'Nepalese Rupee', 'minorUnit' => 2, 'numericCode' => 524, ), 'NZD' => array ( 'alphabeticCode' => 'NZD', 'currency' => 'New Zealand Dollar', 'minorUnit' => 2, 'numericCode' => 554, ), 'OMR' => array ( 'alphabeticCode' => 'OMR', 'currency' => 'Rial Omani', 'minorUnit' => 3, 'numericCode' => 512, ), 'PAB' => array ( 'alphabeticCode' => 'PAB', 'currency' => 'Balboa', 'minorUnit' => 2, 'numericCode' => 590, ), 'PEN' => array ( 'alphabeticCode' => 'PEN', 'currency' => 'Sol', 'minorUnit' => 2, 'numericCode' => 604, ), 'PGK' => array ( 'alphabeticCode' => 'PGK', 'currency' => 'Kina', 'minorUnit' => 2, 'numericCode' => 598, ), 'PHP' => array ( 'alphabeticCode' => 'PHP', 'currency' => 'Philippine Peso', 'minorUnit' => 2, 'numericCode' => 608, ), 'PKR' => array ( 'alphabeticCode' => 'PKR', 'currency' => 'Pakistan Rupee', 'minorUnit' => 2, 'numericCode' => 586, ), 'PLN' => array ( 'alphabeticCode' => 'PLN', 'currency' => 'Zloty', 'minorUnit' => 2, 'numericCode' => 985, ), 'PYG' => array ( 'alphabeticCode' => 'PYG', 'currency' => 'Guarani', 'minorUnit' => 0, 'numericCode' => 600, ), 'QAR' => array ( 'alphabeticCode' => 'QAR', 'currency' => 'Qatari Rial', 'minorUnit' => 2, 'numericCode' => 634, ), 'RON' => array ( 'alphabeticCode' => 'RON', 'currency' => 'Romanian Leu', 'minorUnit' => 2, 'numericCode' => 946, ), 'RSD' => array ( 'alphabeticCode' => 'RSD', 'currency' => 'Serbian Dinar', 'minorUnit' => 2, 'numericCode' => 941, ), 'RUB' => array ( 'alphabeticCode' => 'RUB', 'currency' => 'Russian Ruble', 'minorUnit' => 2, 'numericCode' => 643, ), 'RWF' => array ( 'alphabeticCode' => 'RWF', 'currency' => 'Rwanda Franc', 'minorUnit' => 0, 'numericCode' => 646, ), 'SAR' => array ( 'alphabeticCode' => 'SAR', 'currency' => 'Saudi Riyal', 'minorUnit' => 2, 'numericCode' => 682, ), 'SBD' => array ( 'alphabeticCode' => 'SBD', 'currency' => 'Solomon Islands Dollar', 'minorUnit' => 2, 'numericCode' => 90, ), 'SCR' => array ( 'alphabeticCode' => 'SCR', 'currency' => 'Seychelles Rupee', 'minorUnit' => 2, 'numericCode' => 690, ), 'SDG' => array ( 'alphabeticCode' => 'SDG', 'currency' => 'Sudanese Pound', 'minorUnit' => 2, 'numericCode' => 938, ), 'SEK' => array ( 'alphabeticCode' => 'SEK', 'currency' => 'Swedish Krona', 'minorUnit' => 2, 'numericCode' => 752, ), 'SGD' => array ( 'alphabeticCode' => 'SGD', 'currency' => 'Singapore Dollar', 'minorUnit' => 2, 'numericCode' => 702, ), 'SHP' => array ( 'alphabeticCode' => 'SHP', 'currency' => 'Saint Helena Pound', 'minorUnit' => 2, 'numericCode' => 654, ), 'SLE' => array ( 'alphabeticCode' => 'SLE', 'currency' => 'Leone', 'minorUnit' => 2, 'numericCode' => 925, ), 'SLL' => array ( 'alphabeticCode' => 'SLL', 'currency' => 'Leone', 'minorUnit' => 2, 'numericCode' => 694, ), 'SOS' => array ( 'alphabeticCode' => 'SOS', 'currency' => 'Somali Shilling', 'minorUnit' => 2, 'numericCode' => 706, ), 'SRD' => array ( 'alphabeticCode' => 'SRD', 'currency' => 'Surinam Dollar', 'minorUnit' => 2, 'numericCode' => 968, ), 'SSP' => array ( 'alphabeticCode' => 'SSP', 'currency' => 'South Sudanese Pound', 'minorUnit' => 2, 'numericCode' => 728, ), 'STN' => array ( 'alphabeticCode' => 'STN', 'currency' => 'Dobra', 'minorUnit' => 2, 'numericCode' => 930, ), 'SVC' => array ( 'alphabeticCode' => 'SVC', 'currency' => 'El Salvador Colon', 'minorUnit' => 2, 'numericCode' => 222, ), 'SYP' => array ( 'alphabeticCode' => 'SYP', 'currency' => 'Syrian Pound', 'minorUnit' => 2, 'numericCode' => 760, ), 'SZL' => array ( 'alphabeticCode' => 'SZL', 'currency' => 'Lilangeni', 'minorUnit' => 2, 'numericCode' => 748, ), 'THB' => array ( 'alphabeticCode' => 'THB', 'currency' => 'Baht', 'minorUnit' => 2, 'numericCode' => 764, ), 'TJS' => array ( 'alphabeticCode' => 'TJS', 'currency' => 'Somoni', 'minorUnit' => 2, 'numericCode' => 972, ), 'TMT' => array ( 'alphabeticCode' => 'TMT', 'currency' => 'Turkmenistan New Manat', 'minorUnit' => 2, 'numericCode' => 934, ), 'TND' => array ( 'alphabeticCode' => 'TND', 'currency' => 'Tunisian Dinar', 'minorUnit' => 3, 'numericCode' => 788, ), 'TOP' => array ( 'alphabeticCode' => 'TOP', 'currency' => 'Pa’anga', 'minorUnit' => 2, 'numericCode' => 776, ), 'TRY' => array ( 'alphabeticCode' => 'TRY', 'currency' => 'Turkish Lira', 'minorUnit' => 2, 'numericCode' => 949, ), 'TTD' => array ( 'alphabeticCode' => 'TTD', 'currency' => 'Trinidad and Tobago Dollar', 'minorUnit' => 2, 'numericCode' => 780, ), 'TWD' => array ( 'alphabeticCode' => 'TWD', 'currency' => 'New Taiwan Dollar', 'minorUnit' => 2, 'numericCode' => 901, ), 'TZS' => array ( 'alphabeticCode' => 'TZS', 'currency' => 'Tanzanian Shilling', 'minorUnit' => 2, 'numericCode' => 834, ), 'UAH' => array ( 'alphabeticCode' => 'UAH', 'currency' => 'Hryvnia', 'minorUnit' => 2, 'numericCode' => 980, ), 'UGX' => array ( 'alphabeticCode' => 'UGX', 'currency' => 'Uganda Shilling', 'minorUnit' => 0, 'numericCode' => 800, ), 'USD' => array ( 'alphabeticCode' => 'USD', 'currency' => 'US Dollar', 'minorUnit' => 2, 'numericCode' => 840, ), 'USN' => array ( 'alphabeticCode' => 'USN', 'currency' => 'US Dollar (Next day)', 'minorUnit' => 2, 'numericCode' => 997, ), 'UYI' => array ( 'alphabeticCode' => 'UYI', 'currency' => 'Uruguay Peso en Unidades Indexadas (UI)', 'minorUnit' => 0, 'numericCode' => 940, ), 'UYU' => array ( 'alphabeticCode' => 'UYU', 'currency' => 'Peso Uruguayo', 'minorUnit' => 2, 'numericCode' => 858, ), 'UYW' => array ( 'alphabeticCode' => 'UYW', 'currency' => 'Unidad Previsional', 'minorUnit' => 4, 'numericCode' => 927, ), 'UZS' => array ( 'alphabeticCode' => 'UZS', 'currency' => 'Uzbekistan Sum', 'minorUnit' => 2, 'numericCode' => 860, ), 'VED' => array ( 'alphabeticCode' => 'VED', 'currency' => 'Bolívar Soberano', 'minorUnit' => 2, 'numericCode' => 926, ), 'VES' => array ( 'alphabeticCode' => 'VES', 'currency' => 'Bolívar Soberano', 'minorUnit' => 2, 'numericCode' => 928, ), 'VND' => array ( 'alphabeticCode' => 'VND', 'currency' => 'Dong', 'minorUnit' => 0, 'numericCode' => 704, ), 'VUV' => array ( 'alphabeticCode' => 'VUV', 'currency' => 'Vatu', 'minorUnit' => 0, 'numericCode' => 548, ), 'WST' => array ( 'alphabeticCode' => 'WST', 'currency' => 'Tala', 'minorUnit' => 2, 'numericCode' => 882, ), 'XAF' => array ( 'alphabeticCode' => 'XAF', 'currency' => 'CFA Franc BEAC', 'minorUnit' => 0, 'numericCode' => 950, ), 'XAG' => array ( 'alphabeticCode' => 'XAG', 'currency' => 'Silver', 'minorUnit' => 0, 'numericCode' => 961, ), 'XAU' => array ( 'alphabeticCode' => 'XAU', 'currency' => 'Gold', 'minorUnit' => 0, 'numericCode' => 959, ), 'XBA' => array ( 'alphabeticCode' => 'XBA', 'currency' => 'Bond Markets Unit European Composite Unit (EURCO)', 'minorUnit' => 0, 'numericCode' => 955, ), 'XBB' => array ( 'alphabeticCode' => 'XBB', 'currency' => 'Bond Markets Unit European Monetary Unit (E.M.U.-6)', 'minorUnit' => 0, 'numericCode' => 956, ), 'XBC' => array ( 'alphabeticCode' => 'XBC', 'currency' => 'Bond Markets Unit European Unit of Account 9 (E.U.A.-9)', 'minorUnit' => 0, 'numericCode' => 957, ), 'XBD' => array ( 'alphabeticCode' => 'XBD', 'currency' => 'Bond Markets Unit European Unit of Account 17 (E.U.A.-17)', 'minorUnit' => 0, 'numericCode' => 958, ), 'XCD' => array ( 'alphabeticCode' => 'XCD', 'currency' => 'East Caribbean Dollar', 'minorUnit' => 2, 'numericCode' => 951, ), 'XDR' => array ( 'alphabeticCode' => 'XDR', 'currency' => 'SDR (Special Drawing Right)', 'minorUnit' => 0, 'numericCode' => 960, ), 'XOF' => array ( 'alphabeticCode' => 'XOF', 'currency' => 'CFA Franc BCEAO', 'minorUnit' => 0, 'numericCode' => 952, ), 'XPD' => array ( 'alphabeticCode' => 'XPD', 'currency' => 'Palladium', 'minorUnit' => 0, 'numericCode' => 964, ), 'XPF' => array ( 'alphabeticCode' => 'XPF', 'currency' => 'CFP Franc', 'minorUnit' => 0, 'numericCode' => 953, ), 'XPT' => array ( 'alphabeticCode' => 'XPT', 'currency' => 'Platinum', 'minorUnit' => 0, 'numericCode' => 962, ), 'XSU' => array ( 'alphabeticCode' => 'XSU', 'currency' => 'Sucre', 'minorUnit' => 0, 'numericCode' => 994, ), 'XTS' => array ( 'alphabeticCode' => 'XTS', 'currency' => 'Codes specifically reserved for testing purposes', 'minorUnit' => 0, 'numericCode' => 963, ), 'XUA' => array ( 'alphabeticCode' => 'XUA', 'currency' => 'ADB Unit of Account', 'minorUnit' => 0, 'numericCode' => 965, ), 'XXX' => array ( 'alphabeticCode' => 'XXX', 'currency' => 'The codes assigned for transactions where no currency is involved', 'minorUnit' => 0, 'numericCode' => 999, ), 'YER' => array ( 'alphabeticCode' => 'YER', 'currency' => 'Yemeni Rial', 'minorUnit' => 2, 'numericCode' => 886, ), 'ZAR' => array ( 'alphabeticCode' => 'ZAR', 'currency' => 'Rand', 'minorUnit' => 2, 'numericCode' => 710, ), 'ZMW' => array ( 'alphabeticCode' => 'ZMW', 'currency' => 'Zambian Kwacha', 'minorUnit' => 2, 'numericCode' => 967, ), 'ZWL' => array ( 'alphabeticCode' => 'ZWL', 'currency' => 'Zimbabwe Dollar', 'minorUnit' => 2, 'numericCode' => 932, ), ); composer.json 0000644 00000006441 15105703714 0007276 0 ustar 00 { "name": "moneyphp/money", "description": "PHP implementation of Fowler's Money pattern", "license": "MIT", "keywords": [ "money", "vo", "value object" ], "authors": [ { "name": "Mathias Verraes", "email": "mathias@verraes.net", "homepage": "http://verraes.net" }, { "name": "Márk Sági-Kazár", "email": "mark.sagikazar@gmail.com" }, { "name": "Frederik Bosch", "email": "f.bosch@genkgo.nl" } ], "homepage": "http://moneyphp.org", "require": { "php": "~8.0.0 || ~8.1.0 || ~8.2.0", "ext-bcmath": "*", "ext-filter": "*", "ext-json": "*" }, "require-dev": { "ext-gmp": "*", "ext-intl": "*", "cache/taggable-cache": "^1.1.0", "doctrine/coding-standard": "^9.0", "doctrine/instantiator": "^1.4.0", "florianv/exchanger": "^2.6.3", "florianv/swap": "^4.3.0", "moneyphp/iso-currencies": "^3.2.1", "moneyphp/crypto-currencies": "^1.0.0", "php-http/message": "^1.11.0", "php-http/mock-client": "^1.4.1", "phpbench/phpbench": "^1.2.5", "phpspec/phpspec": "^7.3", "phpunit/phpunit": "^9.5.4", "psalm/plugin-phpunit": "^0.18.4", "psr/cache": "^1.0.1", "vimeo/psalm": "~5.3.0" }, "suggest": { "ext-gmp": "Calculate without integer limits", "ext-intl": "Format Money objects with intl", "florianv/exchanger": "Exchange rates library for PHP", "florianv/swap": "Exchange rates library for PHP", "psr/cache-implementation": "Used for Currency caching" }, "minimum-stability": "dev", "prefer-stable": true, "autoload": { "psr-4": { "Money\\": "src/" } }, "autoload-dev": { "psr-4": { "Benchmark\\Money\\": "benchmark/", "Tests\\Money\\": "tests/", "spec\\Money\\": "spec/" } }, "config": { "allow-plugins": { "composer/package-versions-deprecated": true, "dealerdirect/phpcodesniffer-composer-installer": true, "ergebnis/composer-normalize": true, "infection/extension-installer": true, "php-http/discovery": false }, "sort-packages": true }, "extra": { "branch-alias": { "dev-master": "3.x-dev" } }, "scripts": { "benchmark": [ "vendor/bin/phpbench run --retry-threshold=3 --iterations=15 --revs=1000 --warmup=2" ], "clean": "rm -rf build/ vendor/", "test": [ "vendor/bin/phpspec run", "vendor/bin/phpunit -v", "vendor/bin/phpbench run", "vendor/bin/psalm", "vendor/bin/phpcs" ], "test-coverage": [ "vendor/bin/phpunit -v --coverage-text --coverage-clover=build/unit_coverage.xml" ], "update-currencies": [ "cp vendor/moneyphp/iso-currencies/resources/current.php resources/currency.php", "cp vendor/moneyphp/crypto-currencies/resources/binance.php resources/binance.php", "php resources/generate-money-factory.php" ] } } phpcs.xml.dist 0000644 00000002665 15105703714 0007361 0 ustar 00 <?xml version="1.0"?> <ruleset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="vendor/squizlabs/php_codesniffer/phpcs.xsd" > <arg name="basepath" value="."/> <arg name="extensions" value="php"/> <arg name="parallel" value="80"/> <arg name="colors"/> <!-- Ignore warnings and show progress of the run --> <arg value="np"/> <!-- spec files do not seem to follow reasonable rules around the type system, and therefore should be ignored from CS --> <!--<file>./spec</file>--> <file>./src</file> <file>./static-analysis</file> <file>./tests</file> <rule ref="Doctrine"> <!-- some variables and method names are not compliant with CS naming patterns --> <exclude name="Squiz.NamingConventions.ValidVariableName.NotCamelCaps"/> <exclude name="PSR1.Methods.CamelCapsMethodName.NotCamelCaps"/> <!-- renaming exceptions in this library is too big of a BC break for no real benefit --> <exclude name="SlevomatCodingStandard.Classes.SuperfluousExceptionNaming.SuperfluousSuffix"/> <!-- language-level non-strict comparison is (consciously) used in the codebase for performance reasons --> <exclude name="SlevomatCodingStandard.Operators.DisallowEqualOperators.DisallowedEqualOperator"/> <exclude name="SlevomatCodingStandard.Operators.DisallowEqualOperators.DisallowedNotEqualOperator"/> </rule> </ruleset> CHANGELOG.md 0000644 00000034267 15105703714 0006374 0 ustar 00 # Change Log All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). ## [Unreleased] ## [4.2.0] - 2023-08-16 ### Added - Teller object to help legacy applications ## [4.1.1] - 2023-04-11 ### Fixed - Optimized result representation for BcMathCalculator - Use sprintf for float to string conversion in swap exchange - Fix rounding to unit with value between 10 and 49 - Return type for DecimalMoneyFormatter::format is numeric-string - Money::ratioOf throws exception if currencies don't match. - Updated currencies: added SLE and VED, removed HRK. - Do not let php-http/discovery change composer.json. ## [4.1.0] - 2022-12-19 ### Added - Full PHP8.2 compatibility ### Fixed - Fix parsing amounts with leading zero's - Fix invalid exception message in DecimalMoneyParser - Upgrade enchant to newer version - Support Psalm 5.3 - Fix ROUND_UP and ROUND_DOWN in roundToUnit ### Changes - `composer.lock` is not committed anymore - MoneyFactory now also contains crypto-currencies ### Added - `CryptoCurrencies` class that serves crypto-currencies from [moneyphp/crypto-currencies](https://github.com/moneyphp/crypto-currencies) ## [4.0.5] - 2022-08-11 ### Fixed - Enabled zend.assertions during CI - Fixed invalid assertions ## [4.0.4] - 2022-05-18 ### Added - Full PHP8.1 compatibility (#670) ### Changes - Dropped mutation testing as the library owners are unfamiliar with it - CHANGELOG BC change improvement ## [4.0.3] - 2021-12-01 ### Fixed - `jsonSerialize` return types, resulting in no PHP 8.1 warnings. - Documentation CI pipeline failure. ## [4.0.2] - 2021-06-30 ### Changes - Added all extensions to `composer.json`, including those bundled with PHP. ### Fixed - Remove all `empty` uses. Money values of '0' gave an assertion error in decimal formats (#655) ## [4.0.1] - 2021-05-25 ### Changed - Allow `int` as multiplier for `Money::multiply` - Allow `int` as divisor for `Money::divide` ## [4.0.0] - 2021-05-17 ### Added - PHP8.0 compatibility (#633 and #619) - Recommendation to use a type-checker like psalm or phpstan - Rounding to units - `Converter#convertAndReturnWithCurrencyPair` to get the combination of the converted money and currency pair - `Converter#convertAgainstCurrencyPair` to convert against a currency pair ### Changed - **[BC break]** BC Math required as it is the default calculator - **[BC break]** The methods `multiply` and `divide` do not accept floating points any more. Callers are required to convert a float to string (e.g. `sprintf('%.14F', $float)`) before calling these methods. - **[BC break]** The constructor of the `FixedExchange` does not accept floating points any more. Callers are required to convert a float to string (e.g. `sprintf('%.14F', $float)`) before calling the constructor. - Allow multiple arguments to `Money#isSameCurrency` - Renamed second parameter of `Parser#parse` to `$fallbackCurrency` ### Fixed - Fix GMP multiply and divide by negative (#640 #626) - Currency code must be uppercase (#639 #638 #637) - The CPU no longer overheats when using this library (#634) - No longer allowing null amount (#615) - Update cached currencies (#583) - Only numeric strings allowed (#575) - Calculator and Number are internal (#465) - Negative ratio in `Money#allocate()` is now allowed (#258) ### Removed - **[BC break]** Removed `PhpCalculator` - **[BC break]** Removed `Currency#isAvailableWithin()` - **[BC break]** Removed string as allowed type for second parameter to `MoneyParser#parse`, only Currency objects are accepted now - **[BC break]** Completely remove float usage, methods now return numeric-strings ## [3.3.1] - 2019-03-13 ### Fixed - GMP: division of negative values - GMP: compare 0.x value ## [3.3.0] - 2019-12-27 ### Changed - Added types for `Money` to be understood as pure/immutable downstream (#576) ### Fixed - JSON serialization (#551) - Several documentation fixes - Minor fixes ## [3.2.1] - 2019-02-07 ### Changed - `Money::allocate` now maintains keys of ratios array - All parsers now emit a deprecation warning when passing currency as string ### Fixed - Docs fix : plus sign in numeric strings is allowed - Added ext-json as required extension - Throw exception in case of empty currency - BCMath calculator now uses scale parameters for addition and subtracting - Fixed allocation remainder bug - Added PHP 7.3 in test suite - Fixed dockerignore to ignore Dockerfile - Fixed Bitcoin parsing bug when using trailing zeros ## [3.2.0] - 2018-12-05 ### Added - [Exchanger](https://github.com/florianv/exchanger) exchange - Generated static factory to help IDEs understand code like `Money::EUR(500)` - Aggregation functions (min, max, avg, sum) ### Changed - `Money::add` and `Money::subtract` now accept variadic arguments ### Fixed - Division causing unnecessary fractional parts - Numeric comparison for negative numbers ## [3.1.3] - 2018-02-16 ### Fixed - Allocation when the amount is smaller than the number of ratios ## [3.1.2] - 2018-02-16 ### Added - `Number::fromNumber` to be used when the actual type is not known ### Changed - Refactored `Number` usage to make the code cleaner and use less casting ### Fixed - Float cast to string issue on certain locales ## [3.1.1] - 2018-01-19 ### Fixed - Float cast to string issue on certain locales - Deal with numbers represented with E-XX ## [3.1.0] - 2018-01-10 ### Added - CurrencyList to instantiate in-memory currencies - modulus method to Money - ratioOf method to Money - Comparator for easier testing Money object with PHPUnit - IntlLocalizedDecimalParser and IntlLocalizedDecimalFormatter ### Changed - `MoneyParser::parse` method now expects a Currency object - Dropped PHP 5.5 ### Deprecated - Passing currency code as string to `MoneyParser::parse` ### Fixed - Do not allocate remainder to a ratio of zero - Conversion result is always 0 when subunit difference is large enough - Unexpected result when converting small Bitcoin amounts - Fixed StyleCI being too aggressive ## [3.0.9] - 2017-11-05 ### Fixed - Bitcoin currency symbol ## [3.0.8] - 2017-10-03 ### Fixed - Rounding issue in Number class. - Reduce composer package file size by leaving out docs and logo. - Missing Travis tests for PHP 7.2. ## [3.0.7] - 2017-08-07 ### Changed - Currencies ## [3.0.6] - 2017-07-25 ### Added - IndirectExchange: a way to get an exchange rate through a minimal set of intermediate conversions. ### Fixed - Tests for HHVM - Incorrect documentation on Bitcoin parser ## [3.0.5] - 2017-04-26 ### Added - numericCodeFor method to ISOCurrencies ## [3.0.4] - 2017-04-21 ### Added - Negative method ### Changed - Updated ISO Currencies - Removed old Belarusian ruble from ISOCurrencies (BYR) ### Fixed - ISOCurrencies will no longer have a blank currency - Double symbol when formatting negative Bitcoin amounts ## [3.0.3] - 2017-03-22 ### Fixed - Parsing empty strings and number starting or ending with a decimal point for DecimalMoneyParser - Parsing zero for DecimalMoneyParser - Multiplying and dividing with a locale that use commas as separator ## [3.0.2] - 2017-03-11 ### Fixed - BCMath / GMP: comparing values smaller than one - GMP: multiplying with zero - ISOCurrencies: minor refactoring, remove duplication of code ## [3.0.1] - 2017-02-14 ### Added - Reversed Currencies Exchange to try resolving reverse of a currency pair - Documentation on allowed integer(ish) values when constructing Money ### Fixed - Passing integer validation when chunk started with a dash - Passing integer validation when the fractional part started with a dash - Formatting problem for Bitcoin currency with small amounts in PHP < 7.0 - Money constructed from a string with fractional zeroes equals to a Money constructed without the fractional part (eg. `'5.00'` and `'5'`) ## [3.0.0] - 2016-10-26 ### Added - DecimalMoneyFormatter: returns locale-independent raw decimal string ### Changed - **[BC break]** Replaced StringToUnitsParser with DecimalMoneyParser - **[BC break]** Moved `Money\Exception\Exception` to `Money\Exception` - **[BC break]** UnkownCurrencyException is now DomainException instead of RuntimeException - **[Doctrine break]** In `Currency` the private variable `name` was renamed to `code`, which could break your Doctrine mapping if you are using embeddables or any other Reflection related implementation. ## [3.0.0-beta.3] - 2016-10-04 ### Added - FixedExchange: returns fixed exchange rates based on a list (array) ### Changed - **[BC break]** Convert method now moved to its own class: Converter - **[BC break]** Exchange had one method getCurrencyPair which is now renamed to quote - Minor documentation issues ### Fixed - Integer detection when the number overflows the integer type and contains zeros - Rounding numbers containg trailing zeros - Converting Money to currency with different number of subunits ## [3.0.0-beta.2] - 2016-08-03 ### Added - PHP Spec tests - absolute method to Money and Calculator - subunitFor method to Currencies - Currencies now extends IteratorAggregate - Library exceptions now implement a common interface - Formatter and Parser implementation are now rounding half up ### Changed - **[BC break]** Dropped PHP 5.4 support - **[BC break]** Intl and Bitcoin formatters and parsers now require Currencies - ISOCurrencies now uses moneyphp/iso-currencies as currency data source ### Fixed - Documentation to be inline with upcoming version 3 - Rounding issues in calculators with negative numbers - Formatting and parser issues for amounts and numbers with a trailing zero - Improved many exception messages - Registration of own Calculator implementations ## [3.0.0-beta] - 2016-03-01 ### Added - Bitcoin parser and formatter - Also checking tests folder for StyleCI ### Fixed - Currencies are now included in the repo - Currency list generation moved to dev dependency: reduces repo size - BC Math calculator adding and subtracting failed when bcscale was set - Parsing zero for StringToUnitsParser ## 3.0.0-alpha - 2016-02-04 ### Added - Currency repositories (ISO currencies included) - Money exchange (including [Swap](https://github.com/florianv/swap) implementation) - Money formatting (including intl formatter) - Money parsing (including intl parser) - Big integer support utilizing different, transparent calculation logic upon availability (bcmath, gmp, plain php) - Money and Currency implements JsonSerializable - Rounding up and down - Allocation to N targets ### Changed - **[BC break]** Money::getAmount() returns a string instead of an int value - **[BC break]** Moved stringToUnits to StringToUnitsParser parser - Library requires at least PHP 5.4 - Library uses PSR-4 ### Fixed - Integer overflow ### Removed - **[BC break]** UnkownCurrency exception - **[BC break]** Currency list is now provided by [umpirsky/currency-list](https://github.com/umpirsky/currency-list/) - **[BC break]** RoundingMode class - **[BC break]** Announced deprecations are removed (Currency::getName, CurrencyPair::getRatio, Money::getUnits) ## Pre 3.0 - 2015-03-23 Minimum php version is now 5.4 - 2015-03-23 JsonSerializable - (... missing changelog because who remembers to document stuff anyway?) - 2014-03-22 Removed \Money\InvalidArgumentException in favour of plain old InvalidArgumentException - 2014-03-22 Introduce RoundingMode object, used to specify desired rounding - 2014-03-22 Introduced RoundingMode backwards compatible API changes to Money::multiply and Money::divide - 2014-03-22 Allow RoundingMode to be specified when converting currencies - 2014-03-22 CurrencyPair has an equals() method - 2013-10-13 Base currency and counter currency in CurrencyPair named correctly. - 2013-01-08 Removed the Doctrine2\MoneyType helper, to be replaced by something better in the future. It's available at https://gist.github.com/4485025 in case you need it. - 2013-01-08 Use vendor/autoload.php instead of lib/bootstrap.php (or use PSR-0 autolaoding) - 2012-12-10 Renamed Money::getUnits() to Money::getAmount() [Unreleased]: https://github.com/moneyphp/money/compare/v4.1.1...HEAD [4.2.0]: https://github.com/moneyphp/money/compare/v4.1.1...v4.2.0 [4.1.1]: https://github.com/moneyphp/money/compare/v4.1.0...v4.1.1 [4.1.0]: https://github.com/moneyphp/money/compare/v4.0.5...v4.1.0 [4.0.5]: https://github.com/moneyphp/money/compare/v4.0.4...v4.0.5 [4.0.4]: https://github.com/moneyphp/money/compare/v4.0.3...v4.0.4 [4.0.3]: https://github.com/moneyphp/money/compare/v4.0.2...v4.0.3 [4.0.2]: https://github.com/moneyphp/money/compare/v4.0.1...v4.0.2 [4.0.1]: https://github.com/moneyphp/money/compare/v4.0.0...v4.0.1 [4.0.0]: https://github.com/moneyphp/money/compare/v3.3.1...v4.0.0 [3.3.1]: https://github.com/moneyphp/money/compare/v3.3.0...v3.3.1 [3.3.0]: https://github.com/moneyphp/money/compare/v3.2.1...v3.3.0 [3.2.1]: https://github.com/moneyphp/money/compare/v3.2.0...v3.2.1 [3.2.0]: https://github.com/moneyphp/money/compare/v3.1.3...v3.2.0 [3.1.3]: https://github.com/moneyphp/money/compare/v3.1.2...v3.1.3 [3.1.2]: https://github.com/moneyphp/money/compare/v3.1.1...v3.1.2 [3.1.1]: https://github.com/moneyphp/money/compare/v3.1.0...v3.1.1 [3.1.0]: https://github.com/moneyphp/money/compare/v3.0.9...v3.1.0 [3.0.9]: https://github.com/moneyphp/money/compare/v3.0.8...v3.0.9 [3.0.8]: https://github.com/moneyphp/money/compare/v3.0.7...v3.0.8 [3.0.7]: https://github.com/moneyphp/money/compare/v3.0.6...v3.0.7 [3.0.6]: https://github.com/moneyphp/money/compare/v3.0.5...v3.0.6 [3.0.5]: https://github.com/moneyphp/money/compare/v3.0.4...v3.0.5 [3.0.4]: https://github.com/moneyphp/money/compare/v3.0.3...v3.0.4 [3.0.3]: https://github.com/moneyphp/money/compare/v3.0.2...v3.0.3 [3.0.2]: https://github.com/moneyphp/money/compare/v3.0.1...v3.0.2 [3.0.1]: https://github.com/moneyphp/money/compare/v3.0.0...v3.0.1 [3.0.0]: https://github.com/moneyphp/money/compare/v3.0.0-beta.4...v3.0.0 [3.0.0-beta4]: https://github.com/moneyphp/money/compare/v3.0.0-beta.3...v3.0.0-beta.4 [3.0.0-beta3]: https://github.com/moneyphp/money/compare/v3.0.0-beta.2...v3.0.0-beta.3 [3.0.0-beta2]: https://github.com/moneyphp/money/compare/v3.0.0-beta...v3.0.0-beta.2 [3.0.0-beta]: https://github.com/moneyphp/money/compare/v3.0.0-alpha...v3.0.0-beta