diff --git a/lib/RevBank/Global.pm b/lib/RevBank/Global.pm
index a3ce975..e3b3c7c 100644
--- a/lib/RevBank/Global.pm
+++ b/lib/RevBank/Global.pm
@@ -29,7 +29,26 @@ sub import {
         defined $amount or return undef;
         length  $amount or return undef;
 
-        $amount = RevBank::Amount->parse_string($amount) // return undef;
+        my @split = grep /\S/, split /([+-])/, $amount;
+
+        my $posneg = 1;
+        $amount = RevBank::Amount->new(0);
+        for my $token (@split) {
+            if ($token eq '-') {
+                $posneg = $posneg == -1 ? 1 : -1;
+            } elsif ($token eq '+') {
+                next if $posneg == -1;  # -+
+                $posneg ||= 1;
+                next;
+            } else {
+                $posneg or return undef;  # two terms in a row
+                my $term = RevBank::Amount->parse_string($token) // return undef;
+                $amount += $posneg * $term;
+                $posneg = 0;
+            }
+        }
+        $posneg and return undef;  # last token must be term
+
         if ($amount->cents < 0) {
             die "For our sanity, no negative amounts, please :).\n";
         }
diff --git a/revbank b/revbank
index ca23a1c..1a8f2dd 100755
--- a/revbank
+++ b/revbank
@@ -17,7 +17,7 @@ use RevBank::Global;
 use RevBank::Messages;
 use RevBank::Cart;
 
-our $VERSION = "4.2.4";
+our $VERSION = "4.3.0";
 our %HELP1 = (
     "abort" => "Abort the current transaction",
 );
diff --git a/t/calc.t b/t/calc.t
new file mode 100644
index 0000000..0de002a
--- /dev/null
+++ b/t/calc.t
@@ -0,0 +1,56 @@
+use v5.32;
+
+use Test::More;
+use Test::Exception;
+use Test::Warnings ":all";
+
+BEGIN { use_ok('RevBank::Global'); }
+
+dies_ok sub { parse_amount("-1") };
+dies_ok sub { parse_amount("0-42") };
+dies_ok sub { parse_amount("999999") };
+
+is parse_amount("0.123"), undef;
+is parse_amount("42.000"), undef;
+is parse_amount("a"), undef;
+is parse_amount("(1+1)"), undef;
+
+is parse_amount("42")->cents, 4200;
+is parse_amount("42.0")->cents, 4200;
+is parse_amount("42.00")->cents, 4200;
+is parse_amount("1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1")->cents, 4200;
+
+is parse_amount("-42+42")->cents, 0;
+is parse_amount("+42")->cents, 4200;
+is parse_amount("--42")->cents, 4200;
+is parse_amount("+42-42")->cents, 0;
+is parse_amount("0--42")->cents, 4200;
+is parse_amount("0++42")->cents, 4200;
+is parse_amount("42+-42")->cents, 0;
+is parse_amount("42-+42")->cents, 0;
+is parse_amount("0+42")->cents, 4200;
+is parse_amount("42-42")->cents, 0;
+
+is parse_amount(" - 42 + 42")->cents, 0;
+is parse_amount(" + 42 ")->cents, 4200;
+is parse_amount(" - - 42 ")->cents, 4200;
+is parse_amount(" + 42 - 42 ")->cents, 0;
+is parse_amount(" 0 - - 42 ")->cents, 4200;
+is parse_amount(" 0 + + 42 ")->cents, 4200;
+is parse_amount(" 42 + - 42 ")->cents, 0;
+is parse_amount(" 42 - + 42 ")->cents, 0;
+is parse_amount(" 0  + 42 ")->cents, 4200;
+is parse_amount(" 42 - 42 ")->cents, 0;
+
+is parse_amount("-4.20+4.20")->cents, 0;
+is parse_amount("+4.20")->cents, 420;
+is parse_amount("--4.20")->cents, 420;
+is parse_amount("+4.20-4.20")->cents, 0;
+is parse_amount("0--4.20")->cents, 420;
+is parse_amount("0++4.20")->cents, 420;
+is parse_amount("4.20+-4.20")->cents, 0;
+is parse_amount("4.20-+4.20")->cents, 0;
+is parse_amount("0+4.20")->cents, 420;
+is parse_amount("4.20-4.20")->cents, 0;
+
+done_testing;